private CompletableFuture<Void> deepStart(
        Map<Startable, CompletableFuture<Void>> started,
        Stream<? extends Startable> startables
    ) {
        CompletableFuture[] futures = startables
            .sequential()
            .map(it -> {
                // avoid a recursive update in `computeIfAbsent`
                Map<Startable, CompletableFuture<Void>> subStarted = new HashMap<>(started);
                CompletableFuture<Void> future = started.computeIfAbsent(
                    it,
                    startable -> {
                        return deepStart(subStarted, startable.getDependencies().stream())
                            .thenRunAsync(startable::start, EXECUTOR);
                    }
                );
                started.putAll(subStarted);
                return future;
            })
            .toArray(CompletableFuture[]::new);

        return allOfFailfast(futures);
    }
@param started an intermediate storage for already started {@link Startable}s to prevent multiple starts.
@param startables a {@link Stream} of {@link Startable}s to start and scan for transitive dependencies.
core/src/main/java/org/testcontainers/lifecycle/Startables.java