Lift IEventStream, session API + daemon contracts to JasperFx.Events …#268
Merged
Conversation
…for dedupe pillar Foundation drop for the Marten ↔ Polecat dedupe pillar (#214). Adds the database-agnostic contracts both products will inherit so common event-sourcing logic stops living in two parallel implementations. Purely additive — nothing in Marten or Polecat changes yet. JasperFx.Events: - IEventStream<T> — writable stream handle (where T : notnull) - IQueryEventStore — read-side session API (LINQ-returning methods stay product-specific since they return IMartenQueryable / IPolecatQueryable) - IEventOperations — write-side basics (Append × 7, StartStream × 16) - IEventStoreOperations — combined aggregate-handler workflow (FetchForWriting, WriteToAggregate, AppendOptimistic/Exclusive, FetchLatest, ProjectLatest, OverwriteEvent, AssignTagWhere, tag queries, natural-key fetches) - ConcurrencyStyle — was duplicated in both Wolverine integrations JasperFx.Events.Daemon: - IEventFilter — storage-agnostic event-type allowlist - IProjectionDatabase — minimal { Identifier; DatabaseUri } seam - IDaemonChangeListener — post-batch hook (was Polecat's IChangeListener; renamed to avoid clash with Marten's session-level IChangeListener) - IProjectionCoordinator + IProjectionCoordinator<T> — daemon control plane - IProjectionDistributor + IProjectionSet + ProjectionLockIds — shard distribution contracts Updates: - StreamState gains the Marten/Polecat-compatible constructors so the existing class is drop-in for both products - IEventStream<T> takes where T : notnull (matches Marten's broader shape; Polecat will adapt) Excluded from this round (follow-ups): - StreamCompactingRequest<T> + CompactStreamAsync<T> — execution is product-specific; lift the data class in a separate PR - FetchForWritingByTags<T> returning IEventBoundary<T> — blocked on Polecat DCB parity - StreamLatestJson<T> — Marten-specific JSON-passthrough optimization - ProjectionDistributor abstract base + Solo/SingleTenant/MultiTenanted concretes — designed against real consumption call sites in the Marten 9 PR rather than guessed at the seams here Companion: docs/dedupe-namespace-table-2026.md is the canonical reference that Marten 9 / Polecat 4 / Wolverine 6 migration guides will link to. Refs #214 (dedupe pillar), part of #217 (Critter Stack 2026). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 13, 2026
This was referenced May 13, 2026
Closed
jeremydmiller
added a commit
to JasperFx/marten
that referenced
this pull request
May 13, 2026
…ha.6 The contracts lifted in JasperFx/jasperfx#268 are now published as JasperFx.Events 2.0.0-alpha.6 on NuGet. Restores the standard PackageReference path; removes the temporary ProjectReference workaround. - src/Marten/Marten.csproj: ProjectReference → PackageReference. - Directory.Packages.props: JasperFx.Events 2.0.0-alpha.5 → 2.0.0-alpha.6. Build: 0 errors, 1180 warnings (all pre-existing AOT analyzer warnings). Targeted EventSourcingTests on lifted-type files: 4 passed / 4 total on net9.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jeremydmiller
added a commit
to JasperFx/polecat
that referenced
this pull request
May 13, 2026
…ha.6 The contracts lifted in JasperFx/jasperfx#268 are now published as JasperFx.Events 2.0.0-alpha.6 on NuGet. Restores the standard PackageReference path; removes the temporary ProjectReference workaround. - src/Polecat/Polecat.csproj: ProjectReference → PackageReference. - Directory.Packages.props: JasperFx.Events 2.0.0-alpha.5 → 2.0.0-alpha.6. Build still fails (46 errors) — blocked on the gap-fill issues #88 (Append/StartStream overloads), #89 (LoadAsync), #90 (CompletelyReplaceEvent). Those need to land first, then this PR rebases and the consumption-internal issues #91 / #92 get resolved as part of this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
jeremydmiller
added a commit
to JasperFx/polecat
that referenced
this pull request
May 13, 2026
Part of Polecat 4 (#46) under the Critter Stack 2026 dedupe pillar (JasperFx/jasperfx#214). Begins consuming the database-agnostic event-store contracts that landed in JasperFx/jasperfx#268, so Marten and Polecat stop maintaining parallel copies of the same surface. **Status: DRAFT — does not build (46 errors).** Three categories of Polecat-side gap-fills are required before this PR can go green. Filed as separate Polecat issues; see the PR body for the dependency map. Type deletions (force resolution to JasperFx.Events): - Polecat.Events.IEventStream<T> — public interface removed. Internal EventStream<T> now implements JasperFx.Events.IEventStream<T> directly and exposes the Cancellation property the canonical contract requires. - Polecat.Events.StreamState — class removed; file kept as a migration breadcrumb pointing at JasperFx.Events.StreamState. Interface restructuring (Polecat keeps namespace + Polecat-only extras): - Polecat.Events.IQueryEventStore — now inherits JasperFx.Events.IQueryEventStore; keeps QueryRawEventDataOnly<T> + QueryAllRawEvents (return IPolecatQueryable). - Polecat.Events.IEventOperations — now inherits JasperFx.Events.IEventStoreOperations + IQueryEventStore. Keeps Polecat extras: UnArchiveStream, TombstoneStream, FetchForWritingByTags<T> (DCB), CompactStreamAsync<T>. Marten's 3-tier split (IQueryEventStore + IEventOperations + IEventStoreOperations) is the canonical shape per the dedupe pillar — Polecat retains its 2-tier shape for now; structural split is a follow-up. Constraint relaxation: - `where T : class, new()` → `where T : class` in 3 files (EventOperations, QueryEventStore, NaturalKeyFetchPlanner). The new() constraint was defensive — no `new T()` call sites exist in Polecat's event-store impls. Csproj changes (temporary, MUST be reverted before merge): - src/Polecat/Polecat.csproj: JasperFx.Events PackageReference replaced with a ProjectReference to the local JFx.Events worktree. Flip back to PackageReference once 2.0.0-alpha.6+ is published. - Directory.Packages.props: JasperFx 2.0.0-alpha.11 → 2.0.0-alpha.12, JasperFx.Events 2.0.0-alpha.4 → 2.0.0-alpha.5. Refs #46, JasperFx/jasperfx#214, JasperFx/jasperfx#268. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jeremydmiller
added a commit
to JasperFx/polecat
that referenced
this pull request
May 13, 2026
…ha.6 The contracts lifted in JasperFx/jasperfx#268 are now published as JasperFx.Events 2.0.0-alpha.6 on NuGet. Restores the standard PackageReference path; removes the temporary ProjectReference workaround. - src/Polecat/Polecat.csproj: ProjectReference → PackageReference. - Directory.Packages.props: JasperFx.Events 2.0.0-alpha.5 → 2.0.0-alpha.6. Build still fails (46 errors) — blocked on the gap-fill issues #88 (Append/StartStream overloads), #89 (LoadAsync), #90 (CompletelyReplaceEvent). Those need to land first, then this PR rebases and the consumption-internal issues #91 / #92 get resolved as part of this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jeremydmiller
added a commit
to JasperFx/polecat
that referenced
this pull request
May 13, 2026
) * WIP: Consume JFx.Events 2.0 lifted contracts for dedupe pillar Part of Polecat 4 (#46) under the Critter Stack 2026 dedupe pillar (JasperFx/jasperfx#214). Begins consuming the database-agnostic event-store contracts that landed in JasperFx/jasperfx#268, so Marten and Polecat stop maintaining parallel copies of the same surface. **Status: DRAFT — does not build (46 errors).** Three categories of Polecat-side gap-fills are required before this PR can go green. Filed as separate Polecat issues; see the PR body for the dependency map. Type deletions (force resolution to JasperFx.Events): - Polecat.Events.IEventStream<T> — public interface removed. Internal EventStream<T> now implements JasperFx.Events.IEventStream<T> directly and exposes the Cancellation property the canonical contract requires. - Polecat.Events.StreamState — class removed; file kept as a migration breadcrumb pointing at JasperFx.Events.StreamState. Interface restructuring (Polecat keeps namespace + Polecat-only extras): - Polecat.Events.IQueryEventStore — now inherits JasperFx.Events.IQueryEventStore; keeps QueryRawEventDataOnly<T> + QueryAllRawEvents (return IPolecatQueryable). - Polecat.Events.IEventOperations — now inherits JasperFx.Events.IEventStoreOperations + IQueryEventStore. Keeps Polecat extras: UnArchiveStream, TombstoneStream, FetchForWritingByTags<T> (DCB), CompactStreamAsync<T>. Marten's 3-tier split (IQueryEventStore + IEventOperations + IEventStoreOperations) is the canonical shape per the dedupe pillar — Polecat retains its 2-tier shape for now; structural split is a follow-up. Constraint relaxation: - `where T : class, new()` → `where T : class` in 3 files (EventOperations, QueryEventStore, NaturalKeyFetchPlanner). The new() constraint was defensive — no `new T()` call sites exist in Polecat's event-store impls. Csproj changes (temporary, MUST be reverted before merge): - src/Polecat/Polecat.csproj: JasperFx.Events PackageReference replaced with a ProjectReference to the local JFx.Events worktree. Flip back to PackageReference once 2.0.0-alpha.6+ is published. - Directory.Packages.props: JasperFx 2.0.0-alpha.11 → 2.0.0-alpha.12, JasperFx.Events 2.0.0-alpha.4 → 2.0.0-alpha.5. Refs #46, JasperFx/jasperfx#214, JasperFx/jasperfx#268. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Switch JFx.Events from ProjectReference to PackageReference 2.0.0-alpha.6 The contracts lifted in JasperFx/jasperfx#268 are now published as JasperFx.Events 2.0.0-alpha.6 on NuGet. Restores the standard PackageReference path; removes the temporary ProjectReference workaround. - src/Polecat/Polecat.csproj: ProjectReference → PackageReference. - Directory.Packages.props: JasperFx.Events 2.0.0-alpha.5 → 2.0.0-alpha.6. Build still fails (46 errors) — blocked on the gap-fill issues #88 (Append/StartStream overloads), #89 (LoadAsync), #90 (CompletelyReplaceEvent). Those need to land first, then this PR rebases and the consumption-internal issues #91 / #92 get resolved as part of this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Resolve consumption-PR rebase fallout after #93 Post-rebase fixes that landed cleanly once polecat#93 was merged. - IDocumentSession.Events / DocumentSessionBase.Events return types fully-qualified to Polecat.Events.IEventOperations and IQueryEventStore to disambiguate from the JasperFx.Events versions in scope (issues #91 / #92 — consumption-PR-internal). - IQueryEventStore.FetchLatest<T>(Guid|string) kept on Polecat's IQueryEventStore so existing query-session call sites (theStore.QuerySession().Events.FetchLatest<T>(...)) keep working. Marten's canonical position is on IEventStoreOperations (write side) only; Polecat retains the read-side convenience. - Polecat.Events.IEventOperations re-declares FetchLatest<T> with `new` to collapse the diamond between Polecat.IQueryEventStore.FetchLatest and JasperFx.Events.IEventStoreOperations.FetchLatest. Both inherited slots have identical signatures and resolve to the same impl on EventOperations; the `new` declaration just keeps the caller-facing surface unambiguous. Build clean: 0 errors. 39/39 event-store-API tests pass (event_store_api_completeness, fetch_latest, project_latest, start_stream, append_stream). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pull Bot
pushed a commit
to TheTechOddBug/marten
that referenced
this pull request
May 14, 2026
Part of Marten 9 (JasperFx#4349) under the Critter Stack 2026 dedupe pillar (JasperFx/jasperfx#214). Consumes the database-agnostic event-store contracts that landed in JasperFx/jasperfx#268, so Marten and Polecat stop maintaining parallel copies of the same surface. Type deletions (force resolution to JasperFx.Events via existing using JasperFx.Events; imports): - Marten.Events.IEventStream<T> — public interface removed; the internal marker IEventStream is preserved. Marten's EventStream<T> now implements JasperFx.Events.IEventStream<T> directly. Key annotation corrected from string to string? to match the underlying StreamAction.Key. - Marten.Events.StreamState — class removed; the file is kept as a migration breadcrumb pointing at JasperFx.Events.StreamState. Empty-inheriting interfaces (Marten keeps the namespace + Marten-only extras only; everything else is inherited from the JFx canonical): - Marten.Events.IQueryEventStore — keeps QueryRawEventDataOnly<T> + QueryAllRawEvents (return IMartenQueryable). 131 → 28 lines. - Marten.Events.IEventOperations — keeps the two CompactStreamAsync<T> overloads (depend on Marten's StreamCompactingRequest<T>). 234 → 35 lines. - Marten.Events.IEventStoreOperations — keeps FetchForWritingByTags<T> (DCB, returns Marten.Events.Dcb.IEventBoundary<T>) and the two StreamLatestJson<T> overloads (Postgres JSON-passthrough optimization). 485 → 59 lines. - Marten.Events.Daemon.Coordination.IProjectionCoordinator (+ generic variant) — empty inheriting; generic constraint tightened to `where T : class, IDocumentStore` so the inherited JFx.Events.Daemon.IProjectionCoordinator<T>'s `class` constraint is satisfied. 39 → 23 lines. Disambiguation surgery (where both Marten.Events and JasperFx.Events are imported and a name collides): - 3 files: `using StreamState = Marten.Events.StreamState;` → `using StreamState = JasperFx.Events.StreamState;` (BatchedQuery.Events, IBatchedQuery, StorageFeatures). - 4 files: added `using JasperFx.Events;` so `IEventStream<T>` resolves unambiguously (EventStore.WriteToAggregate, the two FetchInlinedPlan partials, StreamStateSelector). - 2 files: fully-qualified `Marten.Events.IEventStoreOperations` where the source intent was the Marten variant — IDocumentOperations.Events return type, DocumentStore.EventStore.cs's CompactStreamAsync reflection target. - 2 files: fully-qualified `Marten.Events.IQueryEventStore` — DocumentSessionBase.CreateEventStore override, DocumentStore.EventStoreExplorer.cs reflection target. - 2 files: replaced `using JasperFx.Events.Daemon;` with a selective `using DaemonMode = JasperFx.Events.Daemon.DaemonMode;` to keep DaemonMode in scope without re-introducing the IProjectionCoordinator ambiguity (HostExtensions, AsyncProjectionTestingExtensions). - 2 files: fully-qualified `Marten.Events.Daemon.Coordination.IProjectionCoordinator` in MartenServiceCollectionExtensions for DI registration. - Generic constraint tightening (13 sites): `where T : IDocumentStore` → `where T : class, IDocumentStore` on extension methods and the concrete Solo/SingleTenant/MultiTenanted coordinators. The JFx-side IProjectionCoordinator<T> has `class` and IDocumentStore being an interface doesn't imply class. Test files (3) updated: same `using JasperFx.Events;` / StreamState alias patterns. Csproj changes (temporary, MUST be reverted before merge): - src/Marten/Marten.csproj: JasperFx.Events PackageReference replaced with a ProjectReference to the local JFx.Events worktree. Flip back to PackageReference once 2.0.0-alpha.6+ is published. - Directory.Packages.props: JasperFx 2.0.0-alpha.9 → 2.0.0-alpha.12, JasperFx.Events 2.0.0-alpha.3 → 2.0.0-alpha.5 (matches the dependency chain pulled in by the JasperFx PR JasperFx#268 contracts). Verification: - `dotnet build src/Marten/Marten.csproj` — 0 errors, 1148 warnings (all pre-existing AOT analyzer warnings, none introduced by this diff). - `dotnet build src/EventSourcingTests/EventSourcingTests.csproj` — 0 errors. - Targeted EventSourcingTests on the lifted-type test files (event_storage_stream_state_selector + Bug_2281_stream_action_without_events_save_changes_throws) — 4 passed / 4 total on net9.0. What this PR does NOT do (deliberate scope cut): - No fetch planner / NaturalKey / IProjectionDistributor consumption. Those rows in `dedupe-namespace-table-2026.md` are still `🔄 in flight` and live in their own follow-up PRs once the call-site design is settled. - No abstract base class for the projection distributor. JasperFx/jasperfx#268 shipped only the interfaces (IProjectionDistributor, IProjectionSet, ProjectionLockIds); the abstract Solo / SingleTenant / MultiTenanted scaffolding is designed against this consumption PR and the parallel Polecat distributor work (JasperFx/polecat#83), in a separate PR. - No `StreamCompactingRequest<T>` lift. The data class stays Marten-side for now because its execution body is Marten-specific. Refs JasperFx#4349 (Marten 9 master plan), JasperFx/jasperfx#214 (dedupe pillar), JasperFx/jasperfx#268 (JFx.Events 2.0 foundation). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 14, 2026
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
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.
…for dedupe pillar
Foundation drop for the Marten ↔ Polecat dedupe pillar (#214). Adds the database-agnostic contracts both products will inherit so common event-sourcing logic stops living in two parallel implementations. Purely additive — nothing in Marten or Polecat changes yet.
JasperFx.Events:
JasperFx.Events.Daemon:
Updates:
Excluded from this round (follow-ups):
Companion: docs/dedupe-namespace-table-2026.md is the canonical reference that Marten 9 / Polecat 4 / Wolverine 6 migration guides will link to.
Refs #214 (dedupe pillar), part of #217 (Critter Stack 2026).