#407 Phase 0: additive per-tenant surface for JasperFx.Events#408
Merged
Conversation
First round of the per-tenant partitioning work (CritterWatch#209). Pure additive surface with zero behavior change -- a null tenant everywhere is store-global, i.e. today's exact behavior. Unblocks Marten's signature-level work on marten#4596. - ShardName: nullable TenantId as a distinct trailing slot (never folded into ShardKey), Compose(...) factory, TryParse(...) for the 2/3/4-segment forms, and a ForTenant(...) helper. Null tenant keeps Identity/RelativeUrl byte-for-byte identical to before. - ShardState + HighWaterStatistics: nullable TenantId, defaults null, serializes null without breaking existing consumers. - Admin-API tenant overloads with default interface implementations that delegate when tenant is null and throw NotSupportedException otherwise, so existing implementers (Marten/Polecat) compile untouched: IEventDatabase (AllProjectionProgress, FindEventStoreFloorAtTimeAsync), IEventStore (GetProjectionStatusesAsync, DeleteProjectionProgressAsync), IProjectionDaemon (RebuildProjectionAsync x2, RewindSubscriptionAsync). APIs that already take a ShardName thread tenant through it. - Tests: ShardName Compose/TryParse round-trip (all segment forms) and ShardState/HighWaterStatistics null tenant serialization. Full EventTests suite green (323/323) on net9.0 and net10.0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Closes the Phase 0 — Surface (additive) portion of #407 (the standalone first PR / "first round of JasperFx work"). Part of the per-tenant partitioning master plan CritterWatch#209.
This is purely additive with zero behavior change — a
nulltenant everywhere is store-global, i.e. today's exact behavior. It unblocks Marten's signature-level work on marten#4596. Phases A (composite replay executor) and 2 (daemon abstractions) are intentionally not in this PR — per the issue they co-evolve with marten#4596 afterward.Changes
ShardNamegrammarTenantId— a distinct trailing slot, never folded intoShardKey.Compose(name, shardKey, tenantId, version)factory +TryParse(...)handling all forms:Name:ShardKey,Name:ShardKey:Tenant,Name:V{n}:ShardKey,Name:V{n}:ShardKey:Tenant.ForTenant(...)helper. Null/empty tenant keepsIdentity/RelativeUrlbyte-for-byte identical to today.State types
TenantIdonShardState(copied fromShardName) andHighWaterStatistics. Defaults null; serializes null without breaking existing consumers.Admin-API tenant overloads (default interface implementations: delegate when tenant is null, throw
NotSupportedExceptionotherwise — so existing implementers compile untouched and override later)IEventDatabase:AllProjectionProgress,FindEventStoreFloorAtTimeAsyncIEventStore/IEventStore<,>:GetProjectionStatusesAsync,DeleteProjectionProgressAsyncIProjectionDaemon:RebuildProjectionAsync(×2),RewindSubscriptionAsyncShardName(ProjectionProgressFor,StartAgentAsync,StopAgentAsync) thread tenant through it — no new methods, per the issue's principle.Tests
ShardNameTests:Compose/TryParseround-trip for 2-/3-/4-segment forms, null-tenant unchanged, empty→global, HighWaterMark,ForTenant.TenantIdSurfaceSerializationTests:ShardState/HighWaterStatisticsserializeTenantIdas null and round-trip a set value.Verification: full
EventTestssuite green — 323/323 on net9.0 and net10.0.🤖 Generated with Claude Code