catch_up() finishing and the subscriber being registered — if an event is appended between those two steps, it could be missedDate: 2026-05-29
Time: 11:12
The observations include the file up to line 200, but LiveProjection starts around line 210+. Let me work with what's available — the key lines are visible: line 225 (store.subscribers.append(self.onevent)) and line 227 (def on_event).
event-sourcing-store/eventstore.py:LiveProjection — Read the full init and on_event to confirm whether any position-based deduplication existsevent-sourcing-store/eventstore.py:appendbatch — Batch append notifies subscribers after all events are stored (line 93-95), creating a different timing window than single appendsubscriber-idempotency — Whether onevent checks self._position before applying, which would be the standard fix for this raceunbundled-database/unbundleddatabase.py — The addderivedsystem with catchup=True (line 431) faces the same pattern — compare how it handles the gapprojection-snapshot-resume-race — After loading a snapshot and calling catchup(), the same duplicate window exists if the subscriber was registered in init_live-projection-subscribes-before-catchup — LiveProjection._init registers the subscriber (line 225) before the user calls catchup(), making duplicate processing possible but event loss impossible in the current designno-concurrency-control-in-event-store — The event store uses no threading primitives (locks, mutexes, or thread-safe collections), relying entirely on single-threaded execution for correctnesssubscriber-notification-is-synchronous — append() notifies subscribers inline (line 64-65) within the same call, meaning the caller blocks until all subscribers have processed the eventcatch-up-uses-event-id-filtering — catchup() calls readall(fromposition=self.position + 1) (line 171) to skip already-processed events, but onevent has no equivalent guard