Skip to content

fix(Couchbase): Treat an already provisioned cluster as configured - #1736

Open
arnelirobles wants to merge 2 commits into
testcontainers:developfrom
arnelirobles:bugfix/1337-couchbase-reuse
Open

fix(Couchbase): Treat an already provisioned cluster as configured#1736
arnelirobles wants to merge 2 commits into
testcontainers:developfrom
arnelirobles:bugfix/1337-couchbase-reuse

Conversation

@arnelirobles

@arnelirobles arnelirobles commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Closes #1337.

The bug

With WithReuse(true), the second StartAsync never completes. It stalls at Couchbase container is starting, performing configuration. and eventually fails with a TimeoutException.

var container = new CouchbaseBuilder(image).WithReuse(true).Build();
await container.StartAsync();   // 23s
await container.StopAsync();
await container.DisposeAsync();

var again = new CouchbaseBuilder(image).WithReuse(true).Build();
await again.StartAsync();       // hangs, then TimeoutException at 5m23s

Root cause, which is not where the issue thread was looking

The discussion assumed the unauthenticated provisioning requests were failing against an already-provisioned cluster. The run never gets that far. ConfigureCouchbaseAsync stalls on its very first step:

private static readonly IWaitUntil WaitUntilNodeIsReady =
    new HttpWaitStrategy().ForPath("/pools").ForPort(MgmtPort);   // no credentials

await WaitStrategy.WaitUntilAsync(() => WaitUntilNodeIsReady.UntilAsync(container),
    TimeSpan.FromSeconds(2), TimeSpan.FromMinutes(5), -1, ct);    // -1 retries

An unprovisioned node answers /pools without credentials. A provisioned one returns 401. So on a reused container the readiness probe can never succeed, and the wait strategy retries a permanent condition for its full five minute budget. The 5m23s failure is that timeout plus the 23s first start.

Measured

Both community-7.0.2 (the pinned test image) and community-7.6.2, fresh node versus provisioned node:

request fresh provisioned
GET /pools no credentials 200 401
GET /pools with credentials 200 200
GET /pools/default no credentials 404 401
GET /pools/default with credentials 404 200

/pools/default does not exist until the cluster is provisioned, so an authenticated 200 there is an unambiguous "the startup callback has already run against this container".

The fix

Two changes, both using the BasicAuthenticationHeader the module already defines:

  1. Send the credentials with the readiness probe, so it tests whether the management API is up rather than whether the cluster is unprovisioned.
  2. Return early from ConfigureCouchbaseAsync when an authenticated GET /pools/default returns 200.

Same shape as #1731: a startup callback that runs on every start has to be idempotent, and a permanent condition should not be handed to a retry loop.

Tests

CouchbaseReuseTest starts the same container three times and asserts a single distinct container id plus a working cluster ping, following MongoDbReplicaSetReuseTest.

  • before this change: TimeoutException after 5m23s
  • after: passes in 24s

The first of the three starts is a normal fresh provisioning, so that path is covered too.

One note on local verification

couchbase:community-7.0.2 has no linux/arm64 manifest, so on Apple silicon the test image cannot run natively. Local runs used community-7.6.2; the 7.0.2 rows in the table above were measured under amd64 emulation and are identical. CI runs amd64, so it will exercise the pinned image normally.

Summary by CodeRabbit

  • Bug Fixes

    • Improved Couchbase startup readiness checks with authenticated validation.
    • Prevented unnecessary reprovisioning when reusing an already configured cluster.
  • Tests

    • Added coverage verifying Couchbase containers can be reused across multiple starts while maintaining connectivity and container identity.

The startup callback runs on every start, so a reused container enters
ConfigureCouchbaseAsync with a cluster that is already provisioned. Its
first step waits on an unauthenticated GET /pools, which a provisioned
node answers with 401, so the wait strategy retries a permanent
condition for its full five minute timeout and the start appears to
hang at "performing configuration".

Send the credentials with that probe so it tests whether the management
API is up rather than whether the cluster is unprovisioned, then skip
the provisioning requests when an authenticated GET /pools/default
returns 200.

Measured on community-7.0.2 and 7.6.2, fresh vs provisioned:

  /pools         no-auth     200 / 401
  /pools         with-auth   200 / 200
  /pools/default with-auth   404 / 200

Adds a reuse test that starts the same container three times. It fails
before this change with a TimeoutException after 5m23s and passes in
24s after it.

Closes testcontainers#1337.
@netlify

netlify Bot commented Aug 11, 2026

Copy link
Copy Markdown

Deploy Preview for testcontainers-dotnet ready!

Name Link
🔨 Latest commit f8b6c1f
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-dotnet/deploys/6a7b40833ee07100081b7b66
😎 Deploy Preview https://deploy-preview-1736--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 11, 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: 775d0b21-a195-43e4-b776-2ed50aa11dee

📥 Commits

Reviewing files that changed from the base of the PR and between aff5481 and f8b6c1f.

📒 Files selected for processing (1)
  • tests/Testcontainers.Couchbase.Tests/CouchbaseReuseTest.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/Testcontainers.Couchbase.Tests/CouchbaseReuseTest.cs

Walkthrough

Couchbase readiness checks now authenticate requests and detect provisioned clusters. Configuration skips repeated setup for reused containers. A Linux-only test verifies connectivity and shared container identity across multiple starts.

Changes

Couchbase reuse handling

Layer / File(s) Summary
Authenticated readiness and provisioning guard
src/Testcontainers.Couchbase/CouchbaseBuilder.cs, src/Testcontainers.Couchbase/Usings.cs
Readiness checks authenticate /pools and verify /pools/default with HTTP 200. Configuration returns early when the cluster is already provisioned.
Reusable container regression test
tests/Testcontainers.Couchbase.Tests/CouchbaseReuseTest.cs, tests/Testcontainers.Couchbase.Tests/Testcontainers.Couchbase.Tests.csproj, tests/Testcontainers.Couchbase.Tests/Usings.cs
The test fixture starts reusable labeled containers, checks Couchbase connectivity, and verifies one shared container ID. The test project adds required package and global namespace references.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CouchbaseBuilder
  participant CouchbaseContainer
  participant CouchbaseReuseTest
  CouchbaseReuseTest->>CouchbaseBuilder: Build reusable container
  CouchbaseBuilder->>CouchbaseContainer: Check authenticated readiness
  CouchbaseContainer-->>CouchbaseBuilder: Report node and provisioned state
  CouchbaseBuilder-->>CouchbaseReuseTest: Complete startup without repeated setup
  CouchbaseReuseTest->>CouchbaseContainer: Ping cluster
  CouchbaseContainer-->>CouchbaseReuseTest: Return services and container identity
Loading

Possibly related PRs

Suggested labels: bug, module

Suggested reviewers: hofmeisteran

Poem

I check each node with care,
With credentials sent through air.
If setup already stands complete,
I skip the work and stay discreet.
Reused containers share one ID,
While tests hop after me.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary Couchbase reuse fix.
Description check ✅ Passed The description explains the bug, root cause, fix, testing, and linked issue, although it does not use every template heading.
Linked Issues check ✅ Passed The changes address issue #1337 by authenticating readiness checks, skipping repeated provisioning, and testing container reuse.
Out of Scope Changes check ✅ Passed The code, test, dependency, and using changes directly support the Couchbase reuse fix and introduce no unrelated scope.
✨ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/Testcontainers.Couchbase.Tests/CouchbaseReuseTest.cs`:
- Around line 36-37: Update the test flow around Cluster.ConnectAsync so the
Couchbase cluster is disposed in a finally block after the ping assertions
complete, including when an assertion fails. Preserve the existing
container.DisposeAsync cleanup workaround and its ResourceReaper session
configuration.
- Around line 54-55: Update the cluster declaration in the test to use
asynchronous disposal with await using, ensuring the connected Cluster remains
available for PingAsync and is disposed after the test operations complete.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 699e738a-7f37-4a9c-96e7-301110a23ea7

📥 Commits

Reviewing files that changed from the base of the PR and between 3d8e7ed and aff5481.

📒 Files selected for processing (5)
  • src/Testcontainers.Couchbase/CouchbaseBuilder.cs
  • src/Testcontainers.Couchbase/Usings.cs
  • tests/Testcontainers.Couchbase.Tests/CouchbaseReuseTest.cs
  • tests/Testcontainers.Couchbase.Tests/Testcontainers.Couchbase.Tests.csproj
  • tests/Testcontainers.Couchbase.Tests/Usings.cs

Comment thread tests/Testcontainers.Couchbase.Tests/CouchbaseReuseTest.cs
Comment thread tests/Testcontainers.Couchbase.Tests/CouchbaseReuseTest.cs Outdated
@HofmeisterAn HofmeisterAn added enhancement New feature or request module An official Testcontainers module labels Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request module An official Testcontainers module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Couchbase container hangs during startup on subsequent launches with reuse enabled

2 participants