Packages
testcontainers
1.5.0
2.3.1
2.3.0
2.2.0
2.1.0
2.1.0-rc1
2.0.0
2.0.0-rc3
2.0.0-rc2
2.0.0-rc
1.14.1
1.14.0
1.13.5
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.12.0
1.11.8
1.11.7
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
1.11.0
1.10.5
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.0
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.0
1.6.0
1.5.1
1.5.0
1.4.2
1.4.1
1.4.0
1.3.1
1.3.0
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-beta.1
1.0.0-beta
0.9.3
0.9.2
0.9.1
0.9.0
Testcontainers is an Elixir library that supports ExUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
Current section
Files
Jump to
Current section
Files
lib/wait_strategy/log_wait_strategy.ex
# SPDX-License-Identifier: MIT
defmodule Testcontainers.LogWaitStrategy do
@moduledoc """
Considers the container as ready as soon as a specific log message is detected in the container's log stream.
"""
@retry_delay 500
defstruct [:log_regex, :timeout, retry_delay: @retry_delay]
# Public interface
@doc """
Creates a new LogWaitStrategy.
This strategy waits until a specific log message, matching the provided regex, appears in the container's log.
"""
def new(log_regex, timeout \\ 5000, retry_delay \\ @retry_delay) do
%__MODULE__{log_regex: log_regex, timeout: timeout, retry_delay: retry_delay}
end
# Private functions and implementations
defimpl Testcontainers.WaitStrategy do
alias Testcontainers.{Docker, Logger}
@impl true
def wait_until_container_is_ready(wait_strategy, container, conn) do
started_at = get_current_time_millis()
wait_for_log_message(wait_strategy, container.container_id, conn, started_at)
end
# Main loop for waiting strategy
defp wait_for_log_message(wait_strategy, container_id, conn, start_time) do
if reached_timeout?(start_time, wait_strategy.timeout) do
{:error, strategy_timed_out(wait_strategy.timeout, start_time), wait_strategy}
else
process_log(wait_strategy, container_id, conn, start_time)
end
end
defp process_log(wait_strategy, container_id, conn, start_time) do
case log_matches?(container_id, wait_strategy.log_regex, conn) do
true ->
:ok
false ->
log_retry_message(container_id, wait_strategy.log_regex, wait_strategy.retry_delay)
:timer.sleep(wait_strategy.retry_delay)
wait_for_log_message(wait_strategy, container_id, conn, start_time)
end
end
defp log_matches?(container_id, log_regex, conn) do
with {:ok, log_output} <- Docker.Api.stdout_logs(container_id, conn) do
Regex.match?(log_regex, log_output)
else
_ -> false
end
end
defp get_current_time_millis(), do: System.monotonic_time(:millisecond)
defp reached_timeout?(start_time, timeout),
do: get_current_time_millis() - start_time > timeout
defp strategy_timed_out(timeout, start_time) do
{:log_wait_strategy, :timeout, timeout,
elapsed_time: get_current_time_millis() - start_time}
end
defp log_retry_message(container_id, log_regex, delay) do
Logger.log(
"Logs in container #{container_id} didn't match regex #{inspect(log_regex)}, retrying in #{delay}ms."
)
end
end
end