Skip to content

fix(MongoDb): Treat an already initiated replica set as success - #1731

Merged
HofmeisterAn merged 2 commits into
testcontainers:developfrom
arnelirobles:bugfix/1722-replica-set-reinitiate
Aug 11, 2026
Merged

HofmeisterAn merged 2 commits into
testcontainers:developfrom
arnelirobles:bugfix/1722-replica-set-reinitiate

Conversation

@arnelirobles

@arnelirobles arnelirobles commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Fixes #1722

The problem

UnsafeStartAsync invokes the startup callback on every start, so a reused container runs InitiateReplicaSetAsync against a replica set that is already initiated.

The script it runs is not idempotent:

var r = rs.initiate({_id:"rs0", members:[{_id:0, host:"127.0.0.1:27017"}]});
quit(r.ok === 1 ? 0 : 1);

On a set that already exists, rs.initiate throws rather than returning a result, so var r is never assigned and mongosh exits non-zero:

MongoServerError: already initialized
  code: 23
  codeName: 'AlreadyInitialized'

WaitStrategy.WaitUntilAsync then retries the script on its interval. The default wait strategy timeout is one hour, which is why the reporter saw the same mongosh exec repeat "without ever resolving".

The fix

Catch the error and treat AlreadyInitialized as success, so the startup callback is idempotent:

try { var r = rs.initiate({...}); quit(r.ok === 1 ? 0 : 1); }
catch (e) { quit(e.codeName === "AlreadyInitialized" ? 0 : 1); }

Any other server error still exits non-zero and is still retried, so a genuinely failing initiation behaves as before.

Testing

MongoDbReplicaSetReuseTest.ReusedContainerStartsAgain starts the same replica set container twice with WithReuse(true), asserts the second start reused the first container, and asserts the replica set is healthy afterwards.

  • Before the change: times out (bounded to 3 minutes in the test so a regression fails rather than hangs).
  • After the change: passes in about 7 seconds.
  • Full Testcontainers.MongoDb.Tests suite: 19 passed, 0 failed.

The test bounds its own wait because the default wait strategy timeout is one hour; without a bound a regression would stall a CI run rather than fail it.

A related defect, not addressed here

While testing this I first wrote the regression test as a stop/start restart rather than reuse, and hit a different problem in WaitIndicateReadiness:

var (stdout, stderr) = await container.GetLogsAsync(since: container.StoppedTime, timestampsEnabled: false);
return _count.Equals(... .Count(line => line.Contains("Waiting for connections")));

It asserts the count is exactly 1 or 2 over logs taken since StoppedTime, which is not restart-safe in either direction:

  • After a restart the window spans the previous and the new boot, so the count exceeds _count and the equality can never hold. The container start hangs.
  • A single stale "Waiting for connections" line from the previous run can satisfy the check before the new mongod is listening, so the start returns early and the next command fails with MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017.

I have kept that out of this pull request since it is a separate defect with its own design question, and raised it separately. Happy to pick it up if you would like it fixed the same way.

Summary by CodeRabbit

  • Bug Fixes

    • Improved MongoDB replica-set startup when reusing or restarting containers.
    • Recognizes an already-initialized replica set as successful, allowing startup callbacks to run safely.
    • Other initialization failures continue to be reported.
  • Tests

    • Added coverage verifying reusable MongoDB replica-set containers can start again successfully and retain replica-set status.
    • Confirmed multiple starts resolve to the same container instance.

The startup callback runs on every start, so a reused container runs the
replica set initiate script against a set that is already initiated. mongosh
throws MongoServerError (code 23, AlreadyInitialized) rather than returning a
result, so the script exits non-zero and the wait strategy retries it until it
times out. The default timeout is one hour, so the caller appears to hang.

Catch that error and exit zero, which makes the callback idempotent.

Adds a reuse test that starts the same replica set container twice. It times
out before this change and completes in a few seconds after it.
@netlify

netlify Bot commented Aug 7, 2026

Copy link
Copy Markdown

Deploy Preview for testcontainers-dotnet ready!

Name Link
🔨 Latest commit 79ca096
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-dotnet/deploys/6a7aabcb8cfd120008e49de8
😎 Deploy Preview https://deploy-preview-1731--testcontainers-dotnet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 05ddc918-42cd-45ea-bdea-a2e2ddfbe423

📥 Commits

Reviewing files that changed from the base of the PR and between 3a5e858 and 79ca096.

📒 Files selected for processing (4)
  • src/Testcontainers.MongoDb/MongoDbBuilder.cs
  • tests/Testcontainers.MongoDb.Tests/MongoDbReplicaSetReuseTest.cs
  • tests/Testcontainers.MongoDb.Tests/Testcontainers.MongoDb.Tests.csproj
  • tests/Testcontainers.MongoDb.Tests/Usings.cs
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/Testcontainers.MongoDb.Tests/Usings.cs
  • src/Testcontainers.MongoDb/MongoDbBuilder.cs

Walkthrough

MongoDB replica-set initialization now succeeds when MongoDB reports AlreadyInitialized. An integration test verifies reusable replica-set startup, container reuse, and valid replica-set status.

Changes

MongoDB replica-set reuse

Layer / File(s) Summary
Replica-set initialization handling
src/Testcontainers.MongoDb/MongoDbBuilder.cs
The initialization script treats AlreadyInitialized as successful and returns failure for other errors or unsuccessful results.
Reusable container integration validation
tests/Testcontainers.MongoDb.Tests/MongoDbReplicaSetReuseTest.cs, tests/Testcontainers.MongoDb.Tests/Testcontainers.MongoDb.Tests.csproj, tests/Testcontainers.MongoDb.Tests/Usings.cs
The test starts three reusable replica-set containers, verifies one shared container ID, checks rs.status().ok, and adds the required test dependency and imports.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: hofmeisteran

Poem

A rabbit sees Mongo start again,
AlreadyInitialized ends the strain.
One container answers every call,
Replica status stays clear for all.
Hop, hop—reuse works well!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix for already initialized MongoDB replica sets.
Description check ✅ Passed The description explains the problem, fix, rationale, testing, and related issue with sufficient detail.
Linked Issues check ✅ Passed The implementation treats AlreadyInitialized as success for reused replica sets while preserving failures for other errors, satisfying issue #1722.
Out of Scope Changes check ✅ Passed The code, regression test, imports, and test dependency directly support the linked issue and PR objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@HofmeisterAn HofmeisterAn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working module An official Testcontainers module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: MongoDB withReuse and withReplica keeps on trying to execute command without ever resolving

2 participants