fix(backend): listen connections reconnect after a dropped connection or a postgres restart and catch up on what they missed
This commit is contained in:
1 parent
17e27beb59
commit
3373c31a02
5 files changed
+129
-54
No files matched your search
@@ -6,7 +6,7 @@ import asyncpg
|
||||
import uvloop
|
||||
|
||||
from dependencies.container import container
|
||||
from utils.env import env
|
||||
from utils.listen import Listener
|
||||
from utils.logging import logger, setup_logging
|
||||
from utils.read.bots import BOTS_CHANGED_CHANNEL
|
||||
from utils.storage import ContentAddressedStorage
|
||||
@@ -24,19 +24,13 @@ async def _retry_loop(registry: BotRegistry) -> None:
|
||||
await registry.sync()
|
||||
|
||||
|
||||
async def _listen_changes(
|
||||
registry: BotRegistry, tasks: set[asyncio.Task]
|
||||
) -> asyncpg.Connection:
|
||||
def on_change(
|
||||
_conn: asyncpg.Connection, _pid: int, _channel: str, _payload: str
|
||||
) -> None:
|
||||
def _change_listener(registry: BotRegistry, tasks: set[asyncio.Task]) -> Listener:
|
||||
def on_change(_payload: str) -> None:
|
||||
task = asyncio.create_task(registry.sync())
|
||||
tasks.add(task)
|
||||
task.add_done_callback(tasks.discard)
|
||||
|
||||
conn = await asyncpg.connect(dsn=env.db.connection_url)
|
||||
await conn.add_listener(BOTS_CHANGED_CHANNEL, on_change)
|
||||
return conn
|
||||
return Listener("watcher", {BOTS_CHANGED_CHANNEL: on_change}, lambda: on_change(""))
|
||||
|
||||
|
||||
async def runner() -> None:
|
||||
@@ -44,7 +38,7 @@ async def runner() -> None:
|
||||
storage = await container.get(ContentAddressedStorage)
|
||||
registry = BotRegistry(pool, storage)
|
||||
tasks: set[asyncio.Task] = set()
|
||||
listen_conn: asyncpg.Connection | None = None
|
||||
listener = _change_listener(registry, tasks)
|
||||
stop = asyncio.Event()
|
||||
asyncio.get_running_loop().add_signal_handler(signal.SIGTERM, stop.set)
|
||||
retry = asyncio.create_task(_retry_loop(registry))
|
||||
@@ -52,16 +46,14 @@ async def runner() -> None:
|
||||
await registry.sync()
|
||||
if not registry.running:
|
||||
logger.warning("[yellow]No bots yet. Add a bot token in the web UI.[/]")
|
||||
listen_conn = await _listen_changes(registry, tasks)
|
||||
await listener.start()
|
||||
logger.info("[green]Bot watcher running.[/]")
|
||||
await stop.wait()
|
||||
finally:
|
||||
retry.cancel()
|
||||
with contextlib.suppress(asyncio.CancelledError):
|
||||
await retry
|
||||
if listen_conn is not None:
|
||||
with contextlib.suppress(Exception):
|
||||
await listen_conn.close()
|
||||
await listener.stop()
|
||||
await registry.close()
|
||||
await container.close()
|
||||
|
||||
|
||||
Reference in new issue
Block a user