1

A very simple flask server gets requests from users and send a post request to an API , wanted to do this asynchronously using httpx (or even aiohttp) , it works fine like this

@app.route('/test' , methods=['GET' , "POST"])
async def send_notification():
    tasks = []
    async with httpx.AsyncClient() as client:
        for i in range(3):
            try:
                tasks.append( send_post_request(client, url_to_send_request_to , headers , data_to_send) )
            except Exception as e:
                return "Error occured" , 200
        await asyncio.gather(*tasks)
    
async def send_post_request(client, url_to_send_request_to , headers , data_to_send):
    await client.post(url , headers=headers , data=data)

That works fine and requests gets sent asynchronously , but since I receive a ton of requests from users , I can't open a new client for every incoming request -well technically it is possible but it requires a lot of ram on the server and it would be wasteful to open that many clients anyway- So , I thought maybe I can create a pool of clients per machine when running the flask app that can be used when receiving a request from the user so even if I get a million requests from the users , I won't create more than 10 clients for example . To acheive this I changed the code to be the below (which doesn't work)

client = httpx.AsyncClient()

@app.route('/test' , methods=['GET' , "POST"])
async def send_notification():
    tasks = []

    for i in range(3):
        try:
           tasks.append( send_post_request(client, url_to_send_request_to , headers , data_to_send) )
        except Exception as e:
            return "Error occured" , 200
    await asyncio.gather(*tasks)
        
async def send_post_request(client, url_to_send_request_to , headers , data_to_send):
    await client.post(url , headers=headers , data=data)

This is exactly the same but instead of creating a new httpx.AsyncClient() for each incoming request , I should be reusing the already created client (This is for simplicity , my goal for production is obviously creating a list of httpx.AsyncClient() and use one of them for each incoming request )

The first request I get, successfully gets processed and we send the post request via the send_post_request() , no issues . But the second GET request I get returns an error RuntimeError: Event loop is closed !! I am not an async expert but I don't think that I am closing the event loop which I assume gets created with the asyncio.gather(*tasks) .. I am not sure why is that happening or how to solve it. Can someone help before I pull out all of my hair :D

Antony
  • 263
  • 1
  • 2
  • 5

0 Answers0