Repository navigation
GH-5673 TombstoneStream (hard stream delete) on JasperFx 2.90.0 - #5674
Merged
Merged
Conversation
Bumps the JasperFx family to 2.90.0 and implements IEventStoreOperations.TombstoneStream(Guid|string) as DeleteStreamOperation, a queued single-statement delete of the stream's tag rows, events and stream row (plus the mt_streams_identity row under strict identity enforcement), scoped to the session tenant under conjoined tenancy. The event sequence is never touched. Fills the EventAuxiliaryOperations.TombstoneStream slot in PostgresEventStoreDialect. Enrolls StreamTombstoningCompliance, flips SupportsTombstoneStream, and adds Marten-specific tests for archived and tenant partitioning, strict identity enforcement, projected documents and the identity mismatch guard. Carries #1018's RequiresUnreferencedCode/RequiresDynamicCode up to RegisterTagType<TTag> and adds the AOT-safe RegisterTagType<TTag, TInner> (unwrapper) backed by TagTypeRegistration.FromUnwrapper. Documents TombstoneStream in docs/events/archiving.md and the AOT tag registration in docs/events/dcb.md. Closes #5673 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8KxC18Q51z5w4u6YARwe4
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 15, 2026
This was referenced Oct 16, 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.
Closes #5673
What
JasperFx 2.90.0. Bumps all five JasperFx pins from 2.88.0. No Weasel bump: 9.45.1, the only newer Weasel, patches the SQL Server and Oracle providers only, and restore and build are clean on 9.45.0.
TombstoneStream(Guid)/TombstoneStream(string)onsession.Events. It is queued and runs atSaveChangesAsync. The work is done by a new internalDeleteStreamOperation, named that way because "tombstone" already means Marten's sequence-gap bookkeeping stream. It goes through the shared seam:PostgresEventStoreDialect.BuildAuxiliaryOperationsnow fills theTombstoneStreamslot, and its doc comment is updated.mt_event_tag_*table (keyed by the stream'sseq_ids), thenmt_events, thenmt_streams_identitywhen strict identity enforcement is on, thenmt_streams. Natural key rows cascade frommt_streams.;-separated statements in a positional-parameter command. Starting extra batch commands inside one operation would breakOperationPage's alignment of one command per operation. All CTEs read the same snapshot, so the tag delete still finds the events, and the FK checks run at the end of the statement. I verified this with partitioned FKs directly in Postgres before writing it.tenant_id. Deleting through the parent tables reaches the archived partition, and the tenant predicate prunes to the tenant's partition underUseTenantPartitionedEvents.EnsureAsGuidStorage/EnsureAsStringStorage, so calling the wrong overload throwsInvalidOperationException.AOT (#1018). The
[RequiresUnreferencedCode]/[RequiresDynamicCode]attributes are carried up toRegisterTagType<TTag>()andRegisterTagType<TTag>(string), on bothIEventStoreOptionsandEventGraph. There is a new trim-safe overload,RegisterTagType<TTag, TInner>(Func<TTag, TInner> unwrapper, string? tableSuffix = null), backed byTagTypeRegistration.FromUnwrapper. Marten builds with no IL2026/IL3050 from tag registration. TheGetMethod(nameof(TagTypeRegistration.Create))auto-discovery lookup is unchanged and still resolves.Tests
All runs are local against Postgres on :5432.
stream_tombstoning_compliance(StreamTombstoningCompliance,SupportsTombstoneStream => true): 9/9.EventSourcingTests/Archiving/tombstoning_streams.cs: 11 facts.UseTenantPartitionedEventsdeletes only the session tenant.src/Marten.slnx: builds with 0 errors.Docs
docs/events/archiving.md: new section "Deleting a Stream Permanently", with a snippet sample and a comparison table againstArchiveStream. It covers queueing untilSaveChangesAsync, tag rows, tenant scoping, the missing-stream no-op, partition coverage, sequence numbers not being reused, and projected documents being left alone.docs/events/dcb.md: new section on registering tag types under trimming or Native AOT.Found along the way (not fixed here)
Archiving a tagged stream under
UseArchivedStreamPartitioningfails with an FK violation.mt_archive_streammoves the events to the archived partition but not the tag rows that reference them (mt_event_tag_*_seq_id_is_archived_fkey). This is unrelated to this change and is noted in the new test. It probably deserves its own issue.🤖 Generated with Claude Code
https://claude.ai/code/session_01J8KxC18Q51z5w4u6YARwe4