Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: waitForHealthy #118

Merged
merged 2 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Ductus.FluentDocker/Builders/ContainerBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,14 @@ public ContainerBuilder WaitForPort(string portAndProto, double millisTimeout =
_config.WaitForPort = new Tuple<string, string, long>(portAndProto, address, Convert.ToInt64(millisTimeout));
return this;
}

public ContainerBuilder WaitForHealthy(TimeSpan timeout = default)
{
if (timeout == default) timeout = TimeSpan.MaxValue;

_config.WaitForHealthy = new Tuple<long>(Convert.ToInt64(timeout.TotalMilliseconds));
return this;
}

public ContainerBuilder WaitForPort(string portAndProto, TimeSpan timeout = default, string address = null)
{
Expand Down Expand Up @@ -585,6 +593,16 @@ private void AddHooks(IService container)
service, "Wait for port");
});

// Wait for healthy when started
if (null != _config.WaitForHealthy)
container.AddHook(ServiceRunningState.Running,
service =>
{
Fd.DisposeOnException(svc =>
((IContainerService) service).WaitForHealthy(_config.WaitForHealthy.Item1),
service, "Wait for healthy");
});

// Wait for http when started
if (null != _config.WaitForHttp && 0 != _config.WaitForHttp.Count)
container.AddHook(ServiceRunningState.Running, service =>
Expand Down
2 changes: 2 additions & 0 deletions Ductus.FluentDocker/Model/Builders/ContainerBuilderConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public ContainerBuilderConfig()
public string[] Arguments { get; set; }
public Tuple<string /*portAndProto*/, string /*address*/ , long /*waitTimeout*/> WaitForPort { get; set; }

public Tuple<long /*waitTimeout*/> WaitForHealthy { get; set; }

public List<ContainerSpecificConfig.WaitForHttpParams> WaitForHttp { get; } =
new List<ContainerSpecificConfig.WaitForHttpParams>();

Expand Down
38 changes: 38 additions & 0 deletions Ductus.FluentDocker/Services/Extensions/ContainerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,44 @@ public static Processes GetRunningProcesses(this IContainerService service)

return service;
}

/// <summary>
/// Waits for the container to be in a healthy state
/// </summary>
/// <param name="service">The service to check processes within.</param>
/// <param name="millisTimeout">Timeout giving up the wait.</param>
/// <returns>The inparam service.</returns>
public static IContainerService WaitForHealthy(this IContainerService service, long millisTimeout = -1)
{
if (service == null)
return null;

Exception exception = null;
var stopwatch = Stopwatch.StartNew();
using (var mre = new ManualResetEventSlim())
{
Timer timer;
using (timer = new Timer(_ =>
{
var config = service.GetConfiguration(true);
if (config?.State?.Health?.Status == HealthState.Healthy)
mre.Set();
if (stopwatch.ElapsedMilliseconds > millisTimeout)
{
exception = new FluentDockerException($"Wait for healthy expired for container {service.Id}");
mre.Set();
}
}, null, 0, 500))

mre.Wait();
timer.Dispose();
}

if (exception != null)
throw exception;

return service;
}

/// <summary>
/// Waits using an arbitrary function.
Expand Down