From ff74573a261b8f5fcb72899a04278a5d051dcbc5 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Mon, 21 Sep 2026 14:57:46 +0200 Subject: [PATCH 1/2] test(stack): capture reopened stack failure diagnostics --- packages/stack/tests/whole-stack/fixture.ts | 5 ++++- packages/stack/tests/whole-stack/scenarios.ts | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/stack/tests/whole-stack/fixture.ts b/packages/stack/tests/whole-stack/fixture.ts index 4bcefe6d60..63f928cafa 100644 --- a/packages/stack/tests/whole-stack/fixture.ts +++ b/packages/stack/tests/whole-stack/fixture.ts @@ -214,7 +214,10 @@ export const wholeStack = Effect.fn("WholeStack.fixture")((runtime: Runtime) => : created; const statuses = yield* Effect.forEach(observed, (instance) => instance.status.pipe( - Effect.map((status) => `${instance.service}=${status.lifecycle}`), + Effect.map( + (status) => + `${instance.service}=${status.lifecycle}(health=${status.health ?? "undefined"},wakeEnabled=${status.wakeEnabled},error=${status.error?.message ?? "undefined"})`, + ), Effect.catchCause(() => Effect.succeed(`${instance.service}=unknown`)), ), ); diff --git a/packages/stack/tests/whole-stack/scenarios.ts b/packages/stack/tests/whole-stack/scenarios.ts index 9a8c93a4c4..1436fe28e2 100644 --- a/packages/stack/tests/whole-stack/scenarios.ts +++ b/packages/stack/tests/whole-stack/scenarios.ts @@ -330,9 +330,9 @@ export const defaultLifecycle = (runtime: Runtime) => stack: reopenedStack, services: yield* reopenedStack.services.list, }; - yield* refreshLogTails(reopened); yield* assertPersistedPolicy(reopened); yield* clearIdleTimers(reopened); + yield* refreshLogTails(reopened); yield* reopened.stack.composition.start; yield* assertColdStart(reopened); const reopenedColdWorkloads = yield* captureWorkloads(runtime, reopened); @@ -471,8 +471,8 @@ export const parallel = (runtime: Runtime) => stack: reopenedLeft, services: yield* reopenedLeft.services.list, }; - yield* refreshLogTails(reopenedLeftFixture); yield* clearIdleTimers(reopenedLeftFixture); + yield* refreshLogTails(reopenedLeftFixture); yield* reopenedLeft.composition.start; expect( yield* sql( From 813b82116d1bf82213cbf2f7c6103c0348c12701 Mon Sep 17 00:00:00 2001 From: Julien Goux Date: Mon, 21 Sep 2026 15:31:03 +0200 Subject: [PATCH 2/2] test(stack): retain failure causes in lifecycle diagnostics --- packages/stack/tests/whole-stack/fixture.ts | 12 ++++++++++-- packages/stack/tests/whole-stack/scenarios.ts | 16 +++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/stack/tests/whole-stack/fixture.ts b/packages/stack/tests/whole-stack/fixture.ts index 63f928cafa..1d93dbacbc 100644 --- a/packages/stack/tests/whole-stack/fixture.ts +++ b/packages/stack/tests/whole-stack/fixture.ts @@ -71,7 +71,13 @@ const watchServiceLogs = Effect.fn("WholeStack.watchServiceLogs")( return [...without, [instance.service, updated] as const]; }), ), - Effect.ignoreCause, + Effect.catchCause((cause) => + Cause.hasInterruptsOnly(cause) + ? Effect.void + : Effect.logError( + `Whole-stack ${instance.service} log stream failed: ${Cause.pretty(cause)}`, + ), + ), ), ), { discard: true }, @@ -218,7 +224,9 @@ export const wholeStack = Effect.fn("WholeStack.fixture")((runtime: Runtime) => (status) => `${instance.service}=${status.lifecycle}(health=${status.health ?? "undefined"},wakeEnabled=${status.wakeEnabled},error=${status.error?.message ?? "undefined"})`, ), - Effect.catchCause(() => Effect.succeed(`${instance.service}=unknown`)), + Effect.catchCause((cause) => + Effect.succeed(`${instance.service}=unknown(${Cause.pretty(cause)})`), + ), ), ); const tails = yield* Ref.get(logTails); diff --git a/packages/stack/tests/whole-stack/scenarios.ts b/packages/stack/tests/whole-stack/scenarios.ts index 1436fe28e2..07e9bfd92b 100644 --- a/packages/stack/tests/whole-stack/scenarios.ts +++ b/packages/stack/tests/whole-stack/scenarios.ts @@ -147,17 +147,23 @@ const stopWithDiagnostics = Effect.fn("WholeStack.stopWithDiagnostics")((fixture fixture.stack.stop.pipe( Effect.catchCause((cause) => Effect.gen(function* () { - const statuses = yield* statusByService(fixture).pipe( - Effect.catchCause(() => Effect.succeed([])), + const statuses = yield* Effect.forEach(serviceNames, (name) => + service(fixture, name).status.pipe( + Effect.map( + (status) => + `${name}=${status.lifecycle}(health=${status.health ?? "undefined"},wakeEnabled=${status.wakeEnabled},error=${status.error?.message ?? "undefined"})`, + ), + Effect.catchCause((statusCause) => + Effect.succeed(`${name}=unknown(${Cause.pretty(statusCause)})`), + ), + ), ); const logs = yield* Ref.get(fixture.logTails); const serviceIds = serviceNames .map((name) => `${name}=${service(fixture, name).id}`) .join(","); yield* Effect.logError( - `Whole-stack stop diagnostics: cause=${Cause.pretty(cause)} serviceIds=${serviceIds} statuses=${statuses - .map(([name, status]) => `${name}=${status.lifecycle}`) - .join(",")} logs=${logs.map(([name, value]) => `${name}: ${value}`).join("\n")}`, + `Whole-stack stop diagnostics: cause=${Cause.pretty(cause)} serviceIds=${serviceIds} statuses=${statuses.join(",")} logs=${logs.map(([name, value]) => `${name}: ${value}`).join("\n")}`, ); return yield* Effect.failCause(cause); }),