Repository navigation
feat: Wait for the test container up to a configurable startup timeout, replace one that does not become reachable, and remove one whose start fails. - #425
Merged
Conversation
…t, replace one that does not become reachable, and remove one whose start fails. The container now starts EventSourcingDB the way all client SDKs do. Each attempt gets the startup timeout, 30 seconds by default and configurable with withStartupTimeout, from creating the container until a ping of /api/v1/ping answers 200, reading the mapped port anew on every poll. A running container that does not become reachable in time is replaced, up to 3 containers. A container that exits fails at once with the last 20 lines of its output, and so does a Docker error, with that error as cause. Every attempt carries the label io.eventsourcingdb.container-start, by which its containers are removed once it fails, also while Docker is still creating them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QykegdHe7vhHMBN3kWxgfH
…gain. testcontainers creates and starts the container again and copies the signing key into it, so the own create and start, the tar writer, and the attached output are gone. Each attempt still carries its own io.eventsourcingdb.container-start label, now set through withLabels, and follows the container by that label from its creation on: it reads the mapped port on every poll, pings /api/v1/ping until it answers 200, which testcontainers waits for through its wait strategy, and fails at once with the last 20 lines of the log, read through testcontainers, if the container exits. If testcontainers gives up on the port of a running container, after 10 seconds or since it cannot find the port on the host, the attempt counts as one whose database did not become reachable, and another container takes its place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QykegdHe7vhHMBN3kWxgfH
…ound the wait for a pending start. A failed removal no longer replaces the error of the attempt, nor stops the remaining attempts. It is reported on a line of its own after the message. The wait for a start that is still pending after the time ran out lasts 10 seconds at most, after which the containers of the attempt are removed by their label nonetheless. An empty log tail reads as "no log available", since testcontainers does not pass on errors of Docker while reading the log. The integration tests get 180 seconds, so that 3 attempts of 30 seconds fit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QykegdHe7vhHMBN3kWxgfH
…ock, the wording of the port errors, and the default timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QykegdHe7vhHMBN3kWxgfH
…ed attempt has ended. Once the wait for a pending start has run out, the attempt goes on without waiting further, and removes the container of the attempt as soon as the start ends. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QykegdHe7vhHMBN3kWxgfH
…e 180 seconds only to the hooks that start containers. The other hooks and the tests keep 60 seconds. The pull test waits 6 seconds against a startup timeout of 5 seconds, and the tests label their containers with a label of their own SDK. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QykegdHe7vhHMBN3kWxgfH
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QykegdHe7vhHMBN3kWxgfH
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the shared start contract for test containers on top of testcontainers'
GenericContainer.GET /api/v1/pinguntil it answers200. testcontainers waits for that through its wait strategy.withStartupTimeout(timeout)takes milliseconds, like the client'sstallTimeout, and defaults to 30 seconds.No host port found for host IP. An exit fails at once with the last 20 lines of the log, and a Docker error fails at once with that error ascause.io.eventsourcingdb.container-start=<random id>, set throughwithLabels, by which its containers are removed once it fails, also when the time runs out while Docker is still creating them. Ryuk works as before.Tests in
src/container/startContainer.test.tsrun against real Docker: unreachable but running, creation outlasting the timeout, exit at once, missing image, Docker failing after creating the container, a port that testcontainers cannot find, and a normal start. Each checks via Docker events how many containers were created and that none is left.src/container/isReachable.test.tschecks that only the status 200 counts.🤖 Generated with Claude Code
https://claude.ai/code/session_01QykegdHe7vhHMBN3kWxgfH