Skip to content

Fix initialization retry and concurrent completion semantics (#85) - #98

Merged
AGiorgetti merged 5 commits into
developfrom
feature/fix-initialization-retry-85
Nov 2, 2026
Merged

AGiorgetti merged 5 commits into
developfrom
feature/fix-initialization-retry-85

Conversation

@AGiorgetti

@AGiorgetti AGiorgetti commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Scope

Addresses #85 independently of #87 and #86, now rebased onto develop bc30a39 (including #101).

  • Serialize initialization under System.Threading.Lock on .NET 9+ and an object lock on older targets; retain a success flag instead of Lazy<bool>.
  • Retain successful initialization only after all existing index and checkpoint-generator setup completes.
  • After failure, a waiting or later caller performs a fresh attempt. Exceptions are not shared or cached between callers.
  • Reject recursive initialization and reset the in-progress flag in finally, including when a recursive exception escapes.
  • Keep setup logic, exception mapping, index definitions and dependencies unchanged. Initialize is synchronous; no async initialization API is added.

Historical tests-first validation (before the simplification)

The original first commit, 13bf041, contains only permanent regression tests. The historical red-test validation below used the original test commit 75ddea0.
Against unchanged product code on MongoDB 7.0.45 / net8.0: 5 failed, 1 passed, 0 skipped.

Six scenarios cover real index-conflict retry, checkpoint-constructor failure after indexes succeed, successful idempotence, gated concurrent success/failure, and caught recursive entry. Those historical tests required concurrent waiters to observe the same failed attempt; the November 2 simplification intentionally replaces that contract with serialized retries. Tests use gates and thread state, not a timing benchmark, and follow Context/Because/Fact conventions.

The recursion regression also caught and rejected an intermediate implementation that could poison Lazy state; the guard at that historical revision passed it.

Historical local validation (before the current rebase)

Previously validated tree: 399ca0fd95914fdfb87c57970e9223001555e90e.

  • Whole solution Release build, including net472: 0 errors, 296 warnings (including existing dependency audit warnings).
  • Each of net8.0/net9.0/net10.0: 6 focused tests passed; 536 core tests passed; 225 adapter tests passed, 1 unchanged known baseline [P2] Exact-ID explain assertion rejects MongoDB 7 IDHACK despite using the _id index #94 failure; 0 skipped.
  • The only adapter failure is Stream_head_delete_by_id_should_use_the_builtin_id_index, the existing IDHACK query-plan portability assertion. No test was suppressed or weakened.
  • Focused command: dotnet test src/NEventStore.Persistence.MongoDB.Tests/NEventStore.Persistence.MongoDB.Core.Tests.csproj -c Release -f net8.0 --filter FullyQualifiedName~Issue_85
  • Independent review found no remaining findings in the final initialization guard and tests.

Local database: MongoDB 7.0.45. MongoDB 8 cannot start on this cloud host because required /sys CPU metadata is unavailable; PR CI at that time used MongoDB 8. net472 was compiled, not executed on Linux. No timing benchmarks. No package, workflow or unrelated fix changes.

Historical GitHub CI

CI run 39969206709 succeeded on head 3fb5929: Ubuntu and Windows builds and all MongoDB 8 Linux net8.0/net9.0/net10.0 test jobs passed. No reruns were needed.

Do not merge or publish packages.

Historical rebase validation (2026-11-01)

Head: 2f74d41cddd80d40d4e16f0b75e23637df4b25eb; tree: a57996e4be797e13259ff50947da5afb111398e0.

  • Preserved the three tests-first, implementation, and changelog commits without a merge commit or squash. All three patches are unchanged by git range-diff; git diff --check passed.
  • Inherits ci: update stable action tags and MongoDB service image #101's updated GitHub Actions and mongo:9.0.4 image. No driver or runner changes were added by this rebase.
  • Current local tests were not run: this executor has no dotnet or Docker. Historical results above are not current-head validation.
  • Exact-head GitHub CI succeeded on the first attempt: push and pull request. Both runs passed Windows and Ubuntu builds and all Linux net8.0/net9.0/net10.0 test jobs using mongo:9.0.4; each test job reported 285 passed, 0 failed, 0 skipped.
  • MongoDB 9 remains a user-approved test trial, not a claim of official driver 3.0 compatibility.

Initialization simplification (2026-11-02)

Head: 9ab5162ac865b3fd87a842e1a643c95fd865a23f.

  • Replaced shared Lazy<bool> attempts with one lock, a success flag, and a recursion guard. Successful initialization remains idempotent; failed initialization releases the lock so the next waiting caller can retry.
  • Updated the concurrent-failure regression to require the waiting caller to retry successfully and subsequent calls to reuse that success. Added an uncaught-recursion recovery regression; seven initialization scenarios now cover the revised contract.
  • Tests are committed separately before implementation, but no local red or green test run is claimed: this executor has no .NET SDK or Docker. Static review and git diff --check passed. Exact-head CI 41525433716 passed on the first attempt: Windows and Ubuntu solution builds succeeded; Linux net8.0/net9.0/net10.0 each reported 286 passed, 0 failed, 0 skipped with MongoDB 9.0.4. This exercises the object-lock path on net8.0 and System.Threading.Lock on net9.0/net10.0. Other target frameworks were compiled, not runtime-tested by this CI matrix.
  • Changelog updated with issue [P1] Initialize reports success after failed or still-running setup #85. No index, checkpoint setup, driver, workflow, runner, or public API changes. The synchronous Initialize method has no async counterpart.

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

@AGiorgetti
AGiorgetti force-pushed the feature/fix-initialization-retry-85 branch from def0073 to 527e8e7 Compare October 29, 2026 10:17
@AGiorgetti
AGiorgetti marked this pull request as ready for review October 29, 2026 10:24
On unchanged product code: 5 failing regressions, 1 passing idempotence test.
Cover index/checkpoint setup, shared concurrent outcomes, and recursive entry.

Co-authored by Alessandro Giorgetti and Codex (OpenAI).
Publish success after setup, let concurrent callers join the same attempt,
and reject recursive initialization without poisoning a running attempt.

Co-authored by Alessandro Giorgetti and Codex (OpenAI).
@AGiorgetti
AGiorgetti force-pushed the feature/fix-initialization-retry-85 branch from 527e8e7 to 2f74d41 Compare November 1, 2026 12:59
Co-authored by Alessandro Giorgetti and Codex (OpenAI).
…lag (#85)

Serialize callers; retry after failure and retain successful initialization.
Use System.Threading.Lock for net9.0+ and object for older targets.

Co-authored by Alessandro Giorgetti and Codex (OpenAI).
@AGiorgetti
AGiorgetti merged commit 96f0398 into develop Nov 2, 2026
10 checks passed
@AGiorgetti
AGiorgetti deleted the feature/fix-initialization-retry-85 branch November 2, 2026 21:14
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