| ... | ... | @@ -11614,9 +11614,22 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 11614 | 11614 | ); |
| 11615 | 11615 | |
| 11616 | 11616 | it.effect.each([ |
| 11617 | | { caseName: "async setup scripts let the turn start before the script exits", async: true }, |
| 11618 | | { caseName: "sync setup scripts hold the turn until the script exits", async: false }, |
| 11619 | | ])("$caseName", ({ async }) => |
| 11617 | { |
| 11618 | caseName: "async setup scripts let the turn start before the script exits", |
| 11619 | async: true, |
| 11620 | cancel: false, |
| 11621 | }, |
| 11622 | { |
| 11623 | caseName: "sync setup scripts hold the turn until the script exits", |
| 11624 | async: false, |
| 11625 | cancel: false, |
| 11626 | }, |
| 11627 | { |
| 11628 | caseName: "cancelling worktree setup publishes its outcome and cleans up the thread", |
| 11629 | async: false, |
| 11630 | cancel: true, |
| 11631 | }, |
| 11632 | ])("$caseName", ({ async, cancel }) => |
| 11620 | 11633 | Effect.gen(function* () { |
| 11621 | 11634 | const dispatchedCommands: Array<OrchestrationCommand> = []; |
| 11622 | 11635 | const scriptExit = yield* Deferred.make<void>(); |
| ... | ... | @@ -11750,6 +11763,26 @@ it.layer(NodeServices.layer)("server router seam", (it) => { |
| 11750 | 11763 | assert.equal(stageStatus(running, "agent"), "pending"); |
| 11751 | 11764 | assert.isFalse(turnStarted()); |
| 11752 | 11765 | |
| 11766 | if (cancel) { |
| 11767 | const cancelled = yield* Effect.scoped( |
| 11768 | withWsRpcClient(wsUrl, (client) => client[WS_METHODS.worktreeSetupCancel]({ threadId })), |
| 11769 | ); |
| 11770 | assert.isTrue(cancelled.cancelled); |
| 11771 | assertTrue(dispatchedCommands.some((command) => command.type === "thread.delete")); |
| 11772 | const outcome = dispatchedCommands.findLast( |
| 11773 | (command) => |
| 11774 | command.type === "thread.activity.append" && command.activity.kind === "worktree-setup", |
| 11775 | ); |
| 11776 | assertTrue(outcome?.type === "thread.activity.append"); |
| 11777 | assert.propertyVal(outcome.activity.payload, "phase", "cancelled"); |
| 11778 | const result = yield* Fiber.join(dispatchFiber).pipe(Effect.result); |
| 11779 | assertTrue(result._tag === "Failure"); |
| 11780 | assert.propertyVal(result.failure, "message", "Worktree setup cancelled."); |
| 11781 | assert.propertyVal(result.failure, "bootstrapThreadDisposition", "deleted"); |
| 11782 | assert.isFalse(turnStarted()); |
| 11783 | return; |
| 11784 | } |
| 11785 | |
| 11753 | 11786 | // The client that sent the message goes away mid-setup (a reload or a |
| 11754 | 11787 | // dropped socket). The bootstrap belongs to the server, not the |
| 11755 | 11788 | // connection: the thread already exists for every client, so it must |