-
-
Notifications
You must be signed in to change notification settings - Fork 1
feat(testing): contract-first CheckpointStore with unified backend verification #234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…mplementations Implements CheckpointStore abstraction per ADR-026 for projector checkpoint tracking. Changes: - Add CheckpointStore trait in eventcore-types with load/save methods - Add InMemoryCheckpointStore in eventcore-memory implementing trait - Add PostgresCheckpointStore in eventcore-postgres with migration - Add contract tests for checkpoint operations (save, load, update, independence) - Refactor ProjectionRunner to be generic over CheckpointStore - Add NoCheckpointStore as default for runners without checkpointing Migration adds eventcore_subscription_versions table: - subscription_name (TEXT PRIMARY KEY) - last_position (UUID) - updated_at (TIMESTAMPTZ with index for monitoring) Contract tests verify: - Basic save and load round-trip - Update overwrites existing checkpoint - Missing checkpoint returns None - Multiple subscriptions are independent Closes eventcore-6ta
86b0195 to
625e195
Compare
Owner
Author
|
This change is part of the following stack: Change managed by git-spice. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clean CheckpointStore implementation. Trait design is solid, both InMemory and Postgres implementations are correct, contract tests are comprehensive.
Merged
jwilger
added a commit
that referenced
this pull request
Dec 29, 2025
## 🤖 New release
* `eventcore-macros`: 0.3.0 -> 0.4.0
* `eventcore-types`: 0.3.0 -> 0.4.0 (✓ API compatible changes)
* `eventcore-postgres`: 0.3.0 -> 0.4.0 (✓ API compatible changes)
* `eventcore`: 0.3.0 -> 0.4.0 (⚠ API breaking changes)
* `eventcore-memory`: 0.3.0 -> 0.4.0 (✓ API compatible changes)
* `eventcore-testing`: 0.3.0 -> 0.4.0 (⚠ API breaking changes)
### ⚠ `eventcore` breaking changes
```text
--- failure method_parameter_count_changed: pub method parameter count changed ---
Description:
A publicly-visible method now takes a different number of parameters.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#fn-change-arity
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.45.0/src/lints/method_parameter_count_changed.ron
Failed in:
eventcore::ProjectionRunner::new now takes 2 parameters instead of 3, in /tmp/.tmpemizEG/eventcore/eventcore/src/projection.rs:196
--- failure method_requires_different_generic_type_params: method now requires a different number of generic type parameters ---
Description:
A method now requires a different number of generic type parameters than it used to. Uses of this method that supplied the previous number of generic types will be broken.
ref: https://doc.rust-lang.org/reference/items/generics.html
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.45.0/src/lints/method_requires_different_generic_type_params.ron
Failed in:
eventcore::ProjectionRunner::with_checkpoint_store takes 1 generic types instead of 0, in /tmp/.tmpemizEG/eventcore/eventcore/src/projection.rs:222
--- failure struct_missing: pub struct removed or renamed ---
Description:
A publicly-visible struct cannot be imported by its prior path. A `pub use` may have been removed, or the struct itself may have been renamed or removed entirely.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#item-remove
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.45.0/src/lints/struct_missing.ron
Failed in:
struct eventcore::LocalCoordinator, previously in file /tmp/.tmpdrFSjc/eventcore/src/projection.rs:221
struct eventcore::CoordinatorGuard, previously in file /tmp/.tmpdrFSjc/eventcore/src/projection.rs:178
struct eventcore::InMemoryCheckpointStore, previously in file /tmp/.tmpdrFSjc/eventcore/src/projection.rs:126
--- failure trait_requires_more_generic_type_params: trait now requires more generic type parameters ---
Description:
A trait now requires more generic type parameters than it used to. Uses of this trait that supplied the previously-required number of generic types will be broken. To fix this, consider supplying default values for newly-added generic types.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-parameter-no-default
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.45.0/src/lints/trait_requires_more_generic_type_params.ron
Failed in:
trait ProjectionRunner (3 -> 4 required generic types) in /tmp/.tmpemizEG/eventcore/eventcore/src/projection.rs:133
--- failure type_requires_more_generic_type_params: type now requires more generic type parameters ---
Description:
A type now requires more generic type parameters than it used to. Uses of this type that supplied the previously-required number of generic types will be broken. To fix this, consider supplying default values for newly-added generic types.
ref: https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-parameter-no-default
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.45.0/src/lints/type_requires_more_generic_type_params.ron
Failed in:
Struct ProjectionRunner (3 -> 4 required generic types) in /tmp/.tmpemizEG/eventcore/eventcore/src/projection.rs:133
```
### ⚠ `eventcore-testing` breaking changes
```text
--- failure declarative_macro_missing: macro_rules declaration removed or renamed ---
Description:
A `macro_rules!` declarative macro cannot be invoked by its prior name. The macro may have been renamed or removed entirely.
ref: https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope
impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.45.0/src/lints/declarative_macro_missing.ron
Failed in:
macro event_store_suite, previously in file /tmp/.tmpdrFSjc/eventcore-testing/src/contract.rs:508
macro event_store_suite, previously in file /tmp/.tmpdrFSjc/eventcore-testing/src/contract.rs:508
macro event_store_contract_tests, previously in file /tmp/.tmpdrFSjc/eventcore-testing/src/contract.rs:407
macro event_store_contract_tests, previously in file /tmp/.tmpdrFSjc/eventcore-testing/src/contract.rs:407
macro event_reader_contract_tests, previously in file /tmp/.tmpdrFSjc/eventcore-testing/src/contract.rs:456
macro event_reader_contract_tests, previously in file /tmp/.tmpdrFSjc/eventcore-testing/src/contract.rs:456
```
<details><summary><i><b>Changelog</b></i></summary><p>
## `eventcore-macros`
<blockquote>
##
[0.3.0](eventcore-macros-v0.2.0...eventcore-macros-v0.3.0)
- 2025-12-27
### Refactoring
- *(release)* switch to workspace version inheritance for full lockstep
versioning ([#221](#221))
</blockquote>
## `eventcore-types`
<blockquote>
##
[0.4.0](eventcore-types-v0.3.0...eventcore-types-v0.4.0)
- 2025-12-29
### Features
- *(eventcore-postgres)* add database triggers to enforce event log
immutability ([#229](#229))
- *(testing)* contract-first CheckpointStore with unified backend
verification ([#234](#234))
</blockquote>
## `eventcore-postgres`
<blockquote>
##
[0.4.0](eventcore-postgres-v0.3.0...eventcore-postgres-v0.4.0)
- 2025-12-29
### Features
- *(eventcore-postgres)* add database triggers to enforce event log
immutability ([#229](#229))
- *(testing)* contract-first CheckpointStore with unified backend
verification ([#234](#234))
### Refactoring
- *(eventcore-postgres)* replace testcontainers with docker-compose
([#224](#224))
- *(testing)* unify contract test macros into backend_contract_tests!
([#233](#233))
</blockquote>
## `eventcore`
<blockquote>
##
[0.4.0](eventcore-v0.3.0...eventcore-v0.4.0)
- 2025-12-29
### Features
- *(testing)* contract-first CheckpointStore with unified backend
verification ([#234](#234))
### Refactoring
- remove vestigial LocalCoordinator and CoordinatorGuard
([#255](#255))
</blockquote>
## `eventcore-memory`
<blockquote>
##
[0.4.0](eventcore-memory-v0.3.0...eventcore-memory-v0.4.0)
- 2025-12-29
### Features
- *(testing)* contract-first CheckpointStore with unified backend
verification ([#234](#234))
</blockquote>
## `eventcore-testing`
<blockquote>
##
[0.4.0](eventcore-testing-v0.3.0...eventcore-testing-v0.4.0)
- 2025-12-29
### Features
- *(testing)* contract-first CheckpointStore with unified backend
verification ([#234](#234))
### Refactoring
- *(testing)* unify contract test macros into backend_contract_tests!
([#233](#233))
</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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Establishes the contract testing pattern for backend implementations: define behavior once, all backends must comply.
This PR demonstrates the unified
backend_contract_tests!macro (from PR #233) by addingCheckpointStorecontract tests that automatically verify both InMemory and Postgres implementations.Key Insight
The migration file is an implementation detail. The real deliverable is:
CheckpointStoretrait defines the contractChanges
New Abstractions
CheckpointStoretrait in eventcore-types (load/save checkpoint positions)InMemoryCheckpointStorein eventcore-memoryPostgresCheckpointStorein eventcore-postgres (with migration)NoCheckpointStoredefault for runners without checkpointingContract Tests Added
checkpoint_save_and_load- basic round-tripcheckpoint_update_overwrites- updates replace previous valuecheckpoint_load_missing_returns_none- missing returns Nonecheckpoint_independent_subscriptions- multiple subscriptions don't interfereRefactoring
ProjectionRunnernow generic overC: CheckpointStoreInMemoryCheckpointStoreremoved from eventcore (was duplicate)Migration
Creates
eventcore_subscription_versionstable per ADR-026:Closes eventcore-6ta