-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow to register application background tasks within an event loop #1092
Comments
From my point of view you are requested for It should be pretty close to already existing If you want to contribute the new signal -- you are welcome. I really appreciate it. Regarding to |
@asvetlov Thanks for such thoughtful answer. I've started to check the signals and even to write some code. But if we gather the
UPDATE By the way can we use nested
And then it will be called in the
In this way we'll run everything that need to complete first in that |
@asvetlov I've started to work on this but got problems with tests I don't get how to solve (see: f0t0n#1 (comment)). I'd appreciate any input on this. |
Your code snippet is incorrect a little bit: |
Ah sure, you're right. Just edited it. |
Should we close it or you do prefer to fix gunicorn worker before? |
Let me fix worker, yea. |
All work is done. |
Long story short
I run an aiohttp application with Gunicorn behind nginx.
The application exposes two websocket connection endpoints for mobile clients: one for RPC and other for Pub/Sub.
When some event is occurred in the system (e,g, there're some news from company for clients) I want to notify all the connected websockets that I store e.g. in my
app['pub_sub_websockets']
. So basically I would iterate them in a loop and send bytes to each one.Each application instance that Gunicorn runs in a separate process has own collection of connected websockets. But I have to notify all the websockets connected to all workers (or even to all workers on all server nodes). Therefore I would proxy the event through some messaging system like Redis Pub/Sub or ZeroMQ. In my case it's ZeroMQ.
The problem is I can't easily setup the "listener" coroutine that will run within the application's event loop to subscribe to ZeroMQ proxy and forward messages to connected websockets.
Therefore I feel like I have to create own ZeroMQ socket zmq.SUB for each of connected websockets inside my websocket request handler and there gather two coroutines - the first will be listening on ws and the second one will be listening on ZeroMQ's socket. So that the amount of ZeroMQ's zmq.SUB sockets will grow linearly depending to the amount of clients connected to the application process via websockets.
Even with this approach I can't tell the application (actually
GunicornWebWorker
) to usezmq.asyncio.ZMQEventLoop
that's required to use withzmq.asyncio
.Expected behaviour
1) I propose to provide an interface from the
web.Application
likeApplication.register_background_task(coro)
that will allow to register as many tasks as needed during the application instance setup to run along withGunicornWebWorker._runner
within the event loop the worker creates, say usingasyncio.gather()
.In this way in my particular case I'd create only one ZeroMQ socket to listen for a topic that will run within the event loop instead of one ZMQ socket per one connected WebSocket.
And if I have to listen more event sources (message queues from different providers, etc.) I'll add one more socket (or other consuming object depending to the event source provider) and not one more thousand sockets for each thousand of currently connected websockets.
2) Also I think there should be some API to choose which event loop class to use inside the
GunicornWebWorker.init_process()
.Say if I understand the ZMQ's documentation correctly I must use
zmq.asyncio.ZMQEventLoop
to deal with ZeroMQ in my asynchronous application but I can't set this type of loop in the worker without creating of own worker class inherited fromGunicornWebWorker
.Maybe the loop creation logic should be separated in own public method that could be overridden or there should be just an option to choose a class of the event loop to use within the worker. By the way maybe then we won't need a separate
GunicornUVLoopWebWorker
class if we'll be able to set an event loop class somewhere?Please tell me if it's possible to introduce the stuff described above in the aiohttp library? Maybe it's just my architectural approach is totally wrong itself? Then I'd be glad to hear some good guidance to correct it.
The text was updated successfully, but these errors were encountered: