-
Notifications
You must be signed in to change notification settings - Fork 420
[Question] Asynchronous NOTIFY listener #567
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
Comments
This should do the trick: conn.add_listener(
'CHANNEL',
functools.partial(asyncio.ensure_future, async_callback()),
) |
Thanks. Would it be an idea for add_listener to take in an awaitable directly? |
I ended up with something like this: async def listener(self):
async def process(*args):
print(args)
# await self.q.put(args)
if not self.conn_listen:
self.conn_listen = await asyncpg.connect(dsn)
await self.conn_listen.add_listener('my_notify_channel',
lambda *args: loop.create_task(process(args))
)
def main():
listener_task=loop.create_task(listener())
loop.run_forever() |
Thank you! I needed this for FastAPI websockets. Your solution is very elegant! |
I second this, it seems a bit weird that the asynchronous Postgres library can't deal with asynchronous callback functions! |
Can you perform asynchronous database operations within the callback function? My attempt to do it doesn't work: def __init__(self):
...
self.conn.add_listener('channel', self.on_notify)
...
def on_notify(self, *args):
asyncio.create_task(self.async_on_notify(*args))
async def async_on_notify(self, *args):
await self.conn.execute(...) It appears to block at the |
I'm not sure what you mean by "block" here. If you mean "coroutine pauses execution", then it's what |
The `Connection.add_listener()`, `Connection.add_log_listener()` and `Connection.add_termination_listener()` now allow coroutine functions as callbacks. Fixes: #567.
Signed-off-by: Theo Brown <[email protected]>
Signed-off-by: Theo Brown <[email protected]>
Yes you can, but you should avoid concurrently using the same connection from two Tasks, by using your own asyncio synchronization mechanism ( |
Yes, I did want it to pause execution. I want to successively (not concurrently) perform several database operations. However, the database operations never successfully execute, which is what has confused me. def async_init(self):
...
self.pool = await asyncpg.create_pool(...)
self.listener_connection = await self.pool.acquire()
await self.listener_connection.add_listener('channel', self.on_notify)
...
def on_notify(self, *args):
asyncio.create_task(self.async_on_notify(*args))
async def async_on_notify(self, *args):
record = await self.pool.fetch(query)
print(record.get('value')) This does not print the value of the record - it doesn't print anything. |
Make sure the listening connection actually lives long enough. The code you provided implies it gets garbage collected after |
The `Connection.add_listener()`, `Connection.add_log_listener()` and `Connection.add_termination_listener()` now allow coroutine functions as callbacks. Fixes: #567.
Ooh good shout! However I'm pretty sure the listener still exists, because if I replace the code in |
The `Connection.add_listener()`, `Connection.add_log_listener()` and `Connection.add_termination_listener()` now allow coroutine functions as callbacks. Fixes: #567.
How would I prevent it from being garbage collected? What's the correct way of initialising a listener that exists for the whole program? |
Hello,
How would one use an async function as the callback of
conn.add_listener
? I would like to relay specific notifications to API calls usingaiohttp.ClientSession
.Thanks,
Tom
The text was updated successfully, but these errors were encountered: