PostgreSQL read_events silently drops events that fail deserialization #372
Labels
No labels
adr
automated
bug
chore
dependencies
documentation
enhancement
epic
github-actions
P1-high
P2-medium
P3-low
release
research
rust
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
jwilger/eventcore#372
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The PostgreSQL
EventReader::read_eventsimplementation silently drops events that fail JSON deserialization via.ok(). This can cause projections to get permanently stuck when the events table contains events of mixed types, because the projection pipeline interprets an empty result as "no more events" and stops.Location
eventcore-postgres/src/lib.rs, lines 336-345:Problem
When
read_eventsfetches N rows from the database but all N fail deserialization, it returns an emptyVec. The caller (projection pipeline) cannot distinguish between:In batch mode, the projection pipeline reads one page and stops. If the first page is entirely non-matching events, the projection terminates, never reaching the matching events further in the table.
Impact
This affects any scenario where the
eventcore_eventstable contains events from multiple event types (which is the expected norm — all events share one table). A projection forEventTypeAcan get stuck behind a block ofEventTypeBevents.In continuous mode, this could cause infinite empty-poll loops with backoff, wasting resources without ever processing events that are waiting in the table.
Possible Fixes
Several approaches, not mutually exclusive:
1. Filter by event type in SQL (preferred)
Store the
event_type_name()in a column and filter in the query:This requires a schema migration to add an
event_typecolumn and backfill it.2. Return position metadata alongside events
Change
read_eventsto return the last position seen (from the raw rows) even if no events deserialized successfully. This lets the projection pipeline advance past non-matching events:3. Log deserialization failures
At minimum, log a warning when deserialization fails so the problem is observable:
4. Advance checkpoint past non-matching events
Track the highest
event_idseen in the raw rows and use it as the checkpoint position, so the next poll starts after all fetched rows regardless of deserialization success.Affected Backends
Related
This was discovered via the stress test projection failure (see related issue), but it's a library-level bug that affects any production deployment with multiple event types.