Reputation: 8585
I have a POST request handler that takes streaming data as input and writes it to AWS APIs. The data is sent to AWS using multiple inner requests, which are made via boto3
. I believe boto3
is blocking but may release the GIL when doing I/O: it seems to use urllib3.connection internally. So I wrapped it in a call to run_in_executor
- something like this cut-down code:
@stream_request_body
class Handler(RequestHandler):
async def prepare(self):
self.parser = BufferedParser()
async def data_received(self, chunk):
complete_part = self.parser.receive(chunk)
if complete_part:
await IOLoop.current().run_in_executor(
None, self.send_via_boto, complete_part)
async def post(self):
self.set_header('Content-Type', 'text/plain')
self.write("OK")
My question is: will the awaited call to send_via_boto
block the client from uploading the next chunk? Do I need to implement something fancier, or should this already be non-blocking?
Upvotes: 0
Views: 504
Reputation: 2154
"block the client from uploading the next chunk" — a client uploads data not to your app directly, but to a TCP socket. That socket has a certain size, i.e. buffer, so if buffer is full, client will wait until it's emptied and then continue upload. Your app, with the help of Tornado, reads from this TCP-socket-buffer and empty it with the part that was read. The process of sending a chunk to AWS won't stop the client from uploading the data to TCP socket, even if you send data to AWS in a blocking way (i.e. without run_in_executor, but you will block your server from serving other requests). If you send data to AWS slower than client uploads, then your app would be bottleneck and will prevent (which is technically not the same as blocking) a client from uploading more.
Upvotes: 1