Fix WaitForLog implementation

This commit is contained in:
Sergei Shitikov
2024-09-01 15:18:05 +02:00
parent 5ee4fdc804
commit de66ea607c
3 changed files with 55 additions and 13 deletions
+1 -1
View File
@@ -12,7 +12,7 @@ class RedisContainer extends GenericContainer
{
parent::__construct('redis:' . $version);
$this->withExposedPorts(6379);
//$this->withWait(new WaitForLog('Ready to accept connections'));
$this->withWait(new WaitForLog('Ready to accept connections'));
}
/**
@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace Testcontainers\Exception;
class ContainerWaitingTimeoutException extends \RuntimeException
{
protected string $containerId;
public function __construct(string $containerId, ?string $message = null, ?\Throwable $previous = null)
{
$this->containerId = $containerId;
$message ??= sprintf('Timeout reached while waiting for container %s', $containerId);
parent::__construct($message, 0, $previous);
}
public function getContainerId(): string
{
return $this->containerId;
}
}
+32 -12
View File
@@ -4,33 +4,53 @@ declare(strict_types=1);
namespace Testcontainers\Wait;
use Docker\API\Runtime\Client\Client;
use Docker\Docker;
use Symfony\Component\Process\Process;
use Testcontainers\Exception\ContainerNotReadyException;
use Testcontainers\Exception\ContainerWaitingTimeoutException;
/**
* Uses $timout and $pollInterval in milliseconds to set the parameters for waiting.
*/
class WaitForLog implements WaitInterface
{
protected Docker $dockerClient;
public function __construct(private string $message, private bool $enableRegex = false)
{
public function __construct(
protected string $message,
protected bool $enableRegex = false,
protected int $timeout = 10000,
protected int $pollInterval = 500
) {
$this->dockerClient = Docker::create();
}
public function wait(string $id): void
{
$logs = $this->dockerClient->containerLogs($id);
$startTime = microtime(true) * 1000;
$output = $logs->getBody()->getContents();
while (true) {
$elapsedTime = (microtime(true) * 1000) - $startTime;
if ($this->enableRegex) {
if (!preg_match($this->message, $output)) {
throw new ContainerNotReadyException($id, new \RuntimeException('Message not found in logs'));
if ($elapsedTime > $this->timeout) {
throw new ContainerWaitingTimeoutException($id);
}
} else {
if (!str_contains($output, $this->message)) {
throw new ContainerNotReadyException($id, new \RuntimeException('Message not found in logs'));
$output = $this->dockerClient
->containerLogs($id, ['stdout' => true, 'stderr' => true], Client::FETCH_RESPONSE)
?->getBody()
->getContents() ?? '';
$output = preg_replace('/[\x00-\x1F\x7F]/u', '', mb_convert_encoding($output, 'UTF-8', 'UTF-8')) ?? '';
if ($this->enableRegex) {
if (preg_match($this->message, $output)) {
return;
}
} elseif (str_contains($output, $this->message)) {
return;
}
usleep($this->pollInterval * 1000);
}
}
}