Files
roboco/tests/integration
Renn F 684e48e901 [F107] defer Redis bus publish until DB commit (no phantom notifications)
deliver() and _persist_and_deliver() ran inside the caller's open
transaction: the notification row was flushed but not committed, yet
NOTIFICATION_SENT was published to the Redis bus immediately. A commit
failure (DB hiccup, constraint, asyncpg error) rolled the row back while
connected WebSocket clients had already received a push for an id that
no longer existed — a phantom notification (notify_get -> NotFoundError).

Added a deferred-publish (transactional-outbox) helper: defer_bus_publish
enqueues the event on session.info and registers one-shot after_commit /
after_rollback listeners on session.sync_session the first time it is
called for that session. On commit, the after_commit listener schedules
the async drain via asyncio.create_task on the running loop (the listener
fires synchronously inside await AsyncSession.commit, so the loop is
active); the task handles are stashed on the session so callers/tests can
await them. On rollback, after_rollback drops the pending queue — a
rolled-back txn emits nothing. deliver() now builds the per-recipient
events up front (data materialized to strings, so deferral is safe even
if the ORM object later expires) and defers each; the delivered_at DB
marker stays in-tx (rolls back with the row). The bus block stays
best-effort (try/except + log) so a bus-init failure never propagates or
rolls back the notification row — matching the prior inline semantics.

This fixes every deliver/_persist_and_deliver caller at once (the two
cited in F107 plus the orchestrator + task.py deliver sites), since they
all commit the session afterward (the deferred publish fires on that
commit; the row is durable by the time the event goes out).
2026-06-28 22:06:56 +02:00
..
2026-05-02 03:11:49 +02:00
2026-05-06 21:02:31 +02:00
2026-06-26 01:43:08 +02:00
2026-05-06 21:02:31 +02:00
2026-06-24 01:15:57 +02:00
2026-06-26 01:43:08 +02:00
2026-06-26 01:43:08 +02:00
2026-06-24 01:15:57 +02:00
2026-06-26 01:43:08 +02:00
2026-05-06 21:02:31 +02:00