Skip to content
Open
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
2 changes: 1 addition & 1 deletion apps/cli/infra/compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ services:
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
start_period: 60s

volumes:
temporal-data:
34 changes: 30 additions & 4 deletions apps/cli/src/docker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,26 @@ export function isTemporalReady(): boolean {
return output.includes('SERVING');
}

/**
* Check if the Temporal container reports healthy via Docker's own healthcheck.
* This avoids racing the compose healthcheck with our own poll loop.
*/
function isContainerHealthy(container: string): boolean {
const status = runOutput('docker', [
'inspect',
'--format',
'{{.State.Health.Status}}',
container,
]);
return status === 'healthy';
}

/**
* Ensure Temporal is running via compose.
*
* The timeout is configurable via SHANNON_TEMPORAL_TIMEOUT_MS (default: 120000).
* On Windows/WSL2, Temporal's SQLite journal writes can take 20-40s longer
* due to NTFS-backed Docker volumes, so the default is generous.
*/
export async function ensureInfra(): Promise<void> {
if (isTemporalReady()) {
Expand All @@ -81,15 +99,23 @@ export async function ensureInfra(): Promise<void> {
console.log('Starting Shannon infrastructure...');
execFileSync('docker', ['compose', '-f', composeFile, 'up', '-d'], { stdio: 'inherit' });

const timeoutMs = Number(process.env.SHANNON_TEMPORAL_TIMEOUT_MS) || 120_000;
const pollIntervalMs = 3_000;
const deadline = Date.now() + timeoutMs;

console.log('Waiting for Temporal to be ready...');
for (let i = 0; i < 30; i++) {
if (isTemporalReady()) {
while (Date.now() < deadline) {
// Prefer Docker's own healthcheck verdict when available
if (isContainerHealthy('shannon-temporal') || isTemporalReady()) {
console.log('Temporal is ready!');
return;
}
await sleep(2000);
await sleep(pollIntervalMs);
}
console.error('Timeout waiting for Temporal');
console.error(
`Timeout waiting for Temporal after ${timeoutMs / 1000}s. ` +
'If you are on Windows/WSL2, try increasing SHANNON_TEMPORAL_TIMEOUT_MS.',
);
process.exit(1);
}

Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ services:
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
start_period: 60s

volumes:
temporal-data: