Sending a request to itself

I am working with legacy code in a Flask application, and I am trying to transfer it into a Sanic application. In the legacy code, the Flask application sends a message to itself to trigger a change in state. This works with no hangups in the Flask application, however when I implement this code directly in Sanic, the Sanic application suffers a read timeout when trying to contact itself. I thought Sanic was non-blocking? I have tried making the endpoint that calls the request sending function and request sending function co-routines, and awaiting the request sending function, but to no avail. Do I need mutex locks in this situation? Why does this technique work in the Flask app, but not in Sanic?

Any help would be greatly appreciated. Thank you all for everything you do. I wish I could participate more and answer questions as well as ask them, but I fear I would just make people dumber.

Sincerely, a dumb guy

First, this does not seem like a dumb question. Don’t be too hard on yourself. I encourage you to join the conversation and not be afraid to dip your toes in the water.

Can you share a snippet of code so I can see what you are trying?

This is the endpoint (one component of the live lock)

@app.route(’/kvs/view-change’, methods=[‘PUT’])

async def view_change(request):

    global state

    view_str = request.json['view']

    print("Start broadcast view change: " + str(state.view))

    await state.broadcast_view(view_str)

    print("Completed broadcast view change: " + str(state.view))

    shards = []

    print("started kvs key count") 

    for address in state.view:

        print(address)

        if address == state.address:

            print("self" + address)

            shards.append({"address":state.address, "key-count":len(state.storage)})

        else:

            print("others" + address)

            r = requests.get(f'http://{address}/kvs/key-count') 

            shards.append({"address":address, "key-count":r.json()['key-count']})

    return response.json({"message": "View change successful","shards":shards}, status=200)

And this is the sending function (the other component of the live lock)

async def broadcast_view(self, view, multi_threaded = False):

    addresses = set(sorted(view.split(',')) + self.view)

    # First send node-change to all nodes.

    for address in addresses:

        State.send_node_change(address, view)

    # Second send key-migration to all nodes.

    if not multi_threaded:

        for address in addresses:

            State.send_key_migration(address, view)

    else:

        threads = []

        for address in addresses:

            threads.append(threading.Thread(target=State.send_key_migration, args=(address, view)))

            threads[-1].start()

        for thread in threads:

            thread.join()

@staticmethod

def send_node_change(address, view):

    print("HELLO FROM send_node_change()!!!!")

    requests.put(f'http://{address}/kvs/node-change', json = {"view":view}, timeout=6, headers = {"Content-Type": "application/json"})

    

@staticmethod

def send_key_migration(address, view):

    print("HELLO FROM send_key_migration()!!!!")

    requests.put(f'http://{address}/kvs/key-migration', json = {"view":view}, timeout=6, headers = {"Content-Type": "application/json"})

The “broadcast_view()” function basically just calls “send_node_change()” for every address in a list of addresses and one of the addresses is its own address, and when the app tries to contact itself, it suffers a read timeout…any idea what’s going on?

I’m in my phone and only did a real quick look at your code. But I noticed you are yang requests which is a blocking library.

Instead, swap it for something like the async client on httpx: https://www.python-httpx.org/

Requests will pause the execution of the server until a response is returned.