top | item 41864306

(no title)

E_Bfx | 1 year ago

Hello, could you elaborate on the footgun with mixing sync and asyncio ? I am currently devellopin one app with both kind of endpoint + websocket and I prefer not discover too late this problems .

discuss

order

flakes|1 year ago

I've found that when mixing the two types of routes, it can be quite easy to accidentally introduce blocking paths which freeze up the main event loop, especially if mixing async dependencies with sync ones.

When a route is async, it gets scheduled on the main event loop, meaning that any blocking calls can block all requests in flight, and block unexpected things like start up and teardown of api handlers. `asyncio.to_thread()` can help here, but it's easy to forget (and there's no warnings in case you forget).

If you do mix the two, I would be very careful to monitor the timings of your requests to detect early if blocking is occurring. For adding these metrics, I suggest using something like statsd or open-telemetry libraries for adding reporting to the endpoints, which you can feed into telemetry dashboards.

eigenvalue|1 year ago

Basically, you want anything that has any kind of IO (network, disk, etc.) or which is very slow to compute to be fully async. If you have a function that returns almost instantly, like computing the hash of something, you can keep that sync.

If you're forced to use a slower sync function (say, something from a library that you can't easily change), then you can use asyncio.to_thread() so that it can run in a separate thread without blocking your main event loop. If you don't do that, then you sort of defeat the whole purpose of the architecture because everything would stop while you're waiting for that slow sync function to return.