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