Skip to content

Fix recycle-bin identity collisions and metadata cleanup ordering (#87) - #97

Draft
AGiorgetti wants to merge 2 commits into
developfrom
feature/fix-recycle-collisions-87
Draft

AGiorgetti wants to merge 2 commits into
developfrom
feature/fix-recycle-collisions-87

Conversation

@AGiorgetti

@AGiorgetti AGiorgetti commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Scope

Addresses #87 using the selected original option 1. Broader lifecycle/recycle-bin redesign is tracked in #96.

  • Assign one random internal stored StreamId per deletion attempt and retain OriginalBucketId/OriginalStreamId.
  • Recycle commits before deleting stream heads and snapshots, in synchronous and asynchronous paths.
  • Preserve public original-stream reads, legacy fallback, checkpoint values and existing cleanup/index definitions.
  • Document rollout, recovery and concurrency limits in docs/Recycle-Bin.md. No index migration, bucket encoding, dependency upgrade or [P2] Exact-ID explain assertion rejects MongoDB 7 IDHACK despite using the _id index #94 change.

Tests first

The first commit, 28ebbd5, contains regression tests only, against unchanged develop 286c0ae:

  • MongoDB 7.0.45 / net10.0: 12 expected failures, 10 passes, 0 skips.
  • Reproduces cross-bucket and delete/recreate collisions on GetFrom_Index, plus metadata removal before a rejected recycle update.

The following fix adds coverage for mixed legacy/new reads, live-document isolation, retained checkpoints, cleanup, and retry from a deliberately seeded partial-update state.

Final local validation

Exact published tree: 096a37f00a7528e037b5dc7b4500080c034741c3.

  • Whole solution Release build, including net472: 0 errors, 319 warnings (including existing dependency audit warnings).
  • On each of net8.0, net9.0 and net10.0: 54 focused tests passed; 536 core tests passed; 273 adapter tests passed and 1 known baseline test failed; 0 skipped.
  • The sole adapter failure is the unchanged [P2] Exact-ID explain assertion rejects MongoDB 7 IDHACK despite using the _id index #94 IDHACK query-plan portability assertion, Stream_head_delete_by_id_should_use_the_builtin_id_index. It has not been suppressed or weakened.
  • Focused command: dotnet test src/NEventStore.Persistence.MongoDB.Tests/NEventStore.Persistence.MongoDB.Core.Tests.csproj -c Release -f net10.0 --filter FullyQualifiedName~Issue_87

MongoDB 7.0.45 was used locally. MongoDB 8 cannot start in this cloud host because required /sys CPU metadata is unavailable; repository PR CI uses MongoDB 8. net472 was compiled, not executed on Linux. No timing benchmarks or performance guarantees. Independent source review found no blocker within the selected bounded scope.

Exact-head GitHub CI

CI run 39966392401 succeeded on head 01b30a1: Ubuntu and Windows builds, plus MongoDB 8 Linux test jobs for net8.0, net9.0 and net10.0 all passed. No rerun was needed.

Compatibility and limits

New code reads existing recycled documents without backfill. Their lost original bucket remains unknown. Public BucketId remains :rb; OriginalBucketId is stored provenance only. Original-stream recycle queries combine matching histories across buckets and deletion attempts.

Old binaries/raw queries expose the synthetic stored ID for new records, so upgrade recycle readers before new-format deletion. UpdateMany is not atomic across documents; retries give remaining live commits another token. No durable lifetime grouping, automatic restart recovery, concurrent-delete/recreate fencing, or atomic lifecycle guarantee is claimed. Tests seed partial persisted state rather than killing a process.

Controlled deletion/recovery must exclude concurrent stream writes/recreation and drain background metadata work; readers needing all-or-nothing visibility also need that boundary. Default metadata writes are unacknowledged, so successful return is not a verified cleanup barrier. Existing asynchronous cancellation defects remain separately scoped to #86.

Draft for review. Do not merge or publish packages as part of this task.

Co-authored by Alessandro Giorgetti and Codex (OpenAI).

Baseline MongoDB 7.0.45/net10 run: 12 expected failures, 10 passes, 0 skips.
Product source is unchanged in this commit.

Co-authored by Alessandro Giorgetti and Codex (OpenAI).
Use per-attempt stored identities with original bucket and stream metadata,
recycle before metadata cleanup, and preserve legacy/public read semantics.
Document recovery limits and follow-up #96.

Co-authored by Alessandro Giorgetti and Codex (OpenAI).
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.

1 participant