Skip to content

Commit f6d1e0f

Browse files
committed
fix(MongoDb): Use db.runCommand({hello:1}) do detect readiness
1 parent 3b4f418 commit f6d1e0f

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

src/Testcontainers.MongoDb/MongoDbBuilder.cs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public MongoDbBuilder WithPassword(string password)
6565
}
6666

6767
/// <summary>
68-
/// Initialize MongoDB as a single-node replica set.
68+
/// Initializes MongoDB as a single-node replica set.
6969
/// </summary>
7070
/// <param name="replicaSetName">The replica set name.</param>
7171
/// <returns>A configured instance of <see cref="MongoDbBuilder" />.</returns>
@@ -97,7 +97,7 @@ public override MongoDbContainer Build()
9797
}
9898
else
9999
{
100-
waitUntil = new WaitInitiateReplicaSet(DockerResourceConfiguration);
100+
waitUntil = new WaitInitiateReplicaSet();
101101
}
102102

103103
// If the user does not provide a custom waiting strategy, append the default MongoDb waiting strategy.
@@ -112,7 +112,8 @@ protected override MongoDbBuilder Init()
112112
.WithImage(MongoDbImage)
113113
.WithPortBinding(MongoDbPort, true)
114114
.WithUsername(DefaultUsername)
115-
.WithPassword(DefaultPassword);
115+
.WithPassword(DefaultPassword)
116+
.WithStartupCallback(InitiateReplicaSetAsync);
116117
}
117118

118119
/// <inheritdoc />
@@ -150,6 +151,34 @@ protected override MongoDbBuilder Merge(MongoDbConfiguration oldValue, MongoDbCo
150151
return new MongoDbBuilder(new MongoDbConfiguration(oldValue, newValue));
151152
}
152153

154+
/// <summary>
155+
/// Initiates the MongoDB replica set.
156+
/// </summary>
157+
/// <param name="container">The container instance.</param>
158+
/// <param name="configuration">The container configuration.</param>
159+
/// <param name="ct">Cancellation token.</param>
160+
/// <returns>Task that completes when the replica set initiation has been executed.</returns>
161+
private async Task InitiateReplicaSetAsync(MongoDbContainer container, MongoDbConfiguration configuration, CancellationToken ct)
162+
{
163+
if (string.IsNullOrEmpty(configuration.ReplicaSetName))
164+
{
165+
return;
166+
}
167+
168+
var scriptContent = $"var r=rs.initiate({{_id:\"{configuration.ReplicaSetName}\",members:[{{_id:0,host:\"127.0.0.1:27017\"}}]}});quit(r.ok===1?0:1);";
169+
170+
var initiate = async () =>
171+
{
172+
var execResult = await container.ExecScriptAsync(scriptContent, ct)
173+
.ConfigureAwait(false);
174+
175+
return 0L.Equals(execResult.ExitCode);
176+
};
177+
178+
await WaitStrategy.WaitUntilAsync(initiate, TimeSpan.FromSeconds(2), TimeSpan.FromMinutes(5), -1, ct)
179+
.ConfigureAwait(false);
180+
}
181+
153182
/// <inheritdoc cref="IWaitUntil" />
154183
private sealed class WaitIndicateReadiness : IWaitUntil
155184
{
@@ -182,16 +211,7 @@ public async Task<bool> UntilAsync(IContainer container)
182211
/// <inheritdoc cref="IWaitUntil" />
183212
private sealed class WaitInitiateReplicaSet : IWaitUntil
184213
{
185-
private readonly string _scriptContent;
186-
187-
/// <summary>
188-
/// Initializes a new instance of the <see cref="WaitInitiateReplicaSet" /> class.
189-
/// </summary>
190-
/// <param name="configuration">The container configuration.</param>
191-
public WaitInitiateReplicaSet(MongoDbConfiguration configuration)
192-
{
193-
_scriptContent = $"try{{rs.status()}}catch(e){{rs.initiate({{_id:'{configuration.ReplicaSetName}',members:[{{_id:0,host:'127.0.0.1:27017'}}]}});throw e;}}";
194-
}
214+
private const string ScriptContent = "var r=db.runCommand({hello:1}).isWritablePrimary;quit(r===true?0:1);";
195215

196216
/// <inheritdoc />
197217
public Task<bool> UntilAsync(IContainer container)
@@ -202,7 +222,7 @@ public Task<bool> UntilAsync(IContainer container)
202222
/// <inheritdoc cref="IWaitUntil.UntilAsync" />
203223
private async Task<bool> UntilAsync(MongoDbContainer container)
204224
{
205-
var execResult = await container.ExecScriptAsync(_scriptContent)
225+
var execResult = await container.ExecScriptAsync(ScriptContent)
206226
.ConfigureAwait(false);
207227

208228
return 0L.Equals(execResult.ExitCode);

0 commit comments

Comments
 (0)