Skip to content

fix: filter read_events by event_type to prevent projection stalls#373

Merged
jwilger merged 1 commit intomainfrom
fix/read-events-event-type-filtering
Apr 15, 2026
Merged

fix: filter read_events by event_type to prevent projection stalls#373
jwilger merged 1 commit intomainfrom
fix/read-events-event-type-filtering

Conversation

@jwilger-ai-bot
Copy link
Copy Markdown
Collaborator

Summary

  • read_events silently drops events that fail deserialization via .ok(), and the LIMIT/.take() is applied before the deserialization filter. When a batch consists entirely of non-matching event types, the projection pipeline sees zero events and stops — permanently stuck.
  • All three backends now filter by event_type at the query/scan level so non-matching events never consume batch slots.
  • The projection pipeline explicitly passes E::event_type_name() in the EventFilter, and all backends fall back to it when no explicit filter is set.

Changes

File Change
eventcore-types/src/projection.rs Add event_type: Option<String> to EventFilter with builder and accessor
eventcore-memory/src/lib.rs Store event_type in GlobalLogEntry, filter before .take()
eventcore-postgres/src/lib.rs Add WHERE event_type = $N to all 4 SQL query branches
eventcore-sqlite/src/lib.rs Add AND event_type = ?N to all 4 SQL query branches
eventcore/src/projection_pipeline.rs Set event_type from E::event_type_name() in ReadEvents effect
eventcore/tests/mixed_event_type_projection_test.rs New test proving the bug and validating the fix
Cargo.lock Update rustls-webpki 0.103.10 → 0.103.12 (security advisory fix)

Test plan

  • New test read_events_returns_matching_events_when_preceded_by_other_types — seeds 5 AlphaEvents + 1 BetaEvent, calls read_events::<BetaEvent> with batch size 3, asserts 1 event returned (was 0 before fix)
  • New test run_projection_processes_events_when_other_event_types_exist — full run_projection integration test with mixed event types
  • All 195 existing tests pass
  • cargo clippy, cargo fmt, cargo audit all clean

Closes #372

When `read_events` is called, the LIMIT/take is applied before
deserialization filtering. If the events table contains events of mixed
types, non-matching events consume batch slots. When an entire batch
consists of non-matching types, the projection pipeline sees zero events
and stops — permanently stuck behind a block of unrelated events.

All three backends (postgres, sqlite, memory) already store event_type
during append. This commit adds event_type filtering at the query/scan
level so non-matching events never consume batch slots:

- Add `event_type` field to `EventFilter` with builder/accessor methods
- In-memory backend: store event_type in GlobalLogEntry, filter before
  .take()
- PostgreSQL backend: add WHERE event_type = $N to all SQL branches
- SQLite backend: add AND event_type = ?N to all SQL branches
- Projection pipeline: set event_type from E::event_type_name() in the
  ReadEvents effect
- All backends fall back to E::event_type_name() when no explicit filter
  is set

Closes #372
@jwilger jwilger enabled auto-merge (squash) April 15, 2026 18:21
@jwilger jwilger merged commit d516c24 into main Apr 15, 2026
18 checks passed
@jwilger jwilger deleted the fix/read-events-event-type-filtering branch April 15, 2026 18:25
@jwilger jwilger mentioned this pull request Apr 15, 2026
jwilger-ai-bot pushed a commit that referenced this pull request Apr 17, 2026
## 🤖 New release

* `eventcore-macros`: 0.7.0 -> 0.7.1
* `eventcore-types`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-postgres`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-sqlite`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-memory`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-testing`: 0.7.0 -> 0.7.1 (✓ API compatible changes)
* `eventcore-examples`: 0.7.0 -> 0.7.1

<details><summary><i><b>Changelog</b></i></summary><p>

## `eventcore-macros`

<blockquote>

##
[0.7.0](eventcore-macros-v0.6.0...eventcore-macros-v0.7.0)
- 2026-04-13

### Bug Fixes

- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- enhance require! macro to accept typed error values
([#335](#335))
- add required event_type_name() to Event trait for stable storage
([#344](#344))

### Miscellaneous Tasks

- adopt han plugins, blueprints, and project conventions
([#330](#330))
- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>

## `eventcore-types`

<blockquote>

##
[0.7.1](eventcore-types-v0.7.0...eventcore-types-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))
</blockquote>

## `eventcore-postgres`

<blockquote>

##
[0.7.1](eventcore-postgres-v0.7.0...eventcore-postgres-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))

### Features

- add load-testing/stress-testing suite
([#370](#370))
</blockquote>

## `eventcore-sqlite`

<blockquote>

##
[0.7.1](eventcore-sqlite-v0.7.0...eventcore-sqlite-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))
</blockquote>

## `eventcore`

<blockquote>

##
[0.7.1](eventcore-v0.7.0...eventcore-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))

### Features

- add load-testing/stress-testing suite
([#370](#370))
</blockquote>

## `eventcore-memory`

<blockquote>

##
[0.7.1](eventcore-memory-v0.7.0...eventcore-memory-v0.7.1)
- 2026-04-15

### Bug Fixes

- filter read_events by event_type to prevent projection stalls
([#373](#373))
</blockquote>

## `eventcore-testing`

<blockquote>

##
[0.7.1](eventcore-testing-v0.7.0...eventcore-testing-v0.7.1)
- 2026-04-15

### Features

- add load-testing/stress-testing suite
([#370](#370))
</blockquote>

## `eventcore-examples`

<blockquote>

##
[0.7.0](eventcore-examples-v0.6.0...eventcore-examples-v0.7.0)
- 2026-04-13

### Bug Fixes

- improve error message consistency, context, and safety across all
crates ([#352](#352))

### Features

- add required event_type_name() to Event trait for stable storage
([#344](#344))
- add TestScenario GWT testing helpers to eventcore-testing
([#346](#346))

### Miscellaneous Tasks

- consolidate workspace lints and enforce strict lint policy
([#351](#351))

### Refactoring

- replace into_inner() with into() for nutype domain types
([#334](#334))
- expose projection config via free function API, then reduce public
surface ([#357](#357))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PostgreSQL read_events silently drops events that fail deserialization

2 participants