If you are creating a web server with aiohttp and want to run a slightly heavy process when receiving an HTTP request [^ job], if you run the process as it is, it will be slow to return an HTTP response, and as a timeout error on the client side It may be processed. Assuming that there is no need to return the processing result, what should I do if I want to return an HTTP response once to end HTTP communication and then perform a little heavy processing?
write_eof </ del>** I found this method not good, so see the postscript. ** **
from asyncio import sleep
from aiohttp import web
async def handler(request):
response = web.Response()
await response.prepare(request)
await response.write_eof()
await sleep(1) #Processing after returning a response
app = web.Application()
app.router.add_get('/', handler)
if __name__ == '__main__':
web.run_app(app)
If nothing is specified when creating the Response object, the HTTP status code is 200.
With the above method, if the connection is maintained for a certain period of time with keep-alive, it happens to work without problems, so I did not notice it, but basically it does not work well.
If you add Connection: close to the response header and disable keep-alive, you can see that the subsequent asynchronous processing is not executed at the time ofwrite_eof ().
Apparently, when the connection with the client is broken, the processing of the request handler is stopped there. (It was hard to find out because there was no error message)
Reference: https://github.com/aio-libs/aiohttp/issues/4773
As a solution, it seems better to use aiojobs.
from asyncio import sleep
from aiohttp import web
import aiojobs.aiohttp as aiojobs
async def job():
"""The process you want to execute after returning a response"""
await sleep(1)
async def handler(request):
await aiojobs.spawn(request, job())
return web.Response(text='ok')
app = web.Application()
app.router.add_get('/', handler)
aiojobs.setup(app)
if __name__ == '__main__':
web.run_app(app)
Recommended Posts