Skip to content

Commit 60b7e18

Browse files
committed
Acknowledge external events after handoff
1 parent 82f5f88 commit 60b7e18

3 files changed

Lines changed: 36 additions & 4 deletions

File tree

src/gateway/dispatch.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ export interface DispatchDeps {
5050
// may retry); filtered/ignored events return true (ack, no retry).
5151
export async function dispatchEvent(deps: DispatchDeps, event: VerifiedEvent): Promise<boolean> {
5252
if (event.provider !== "inkbox") {
53-
if (deps.onExternal) await deps.onExternal(event);
53+
if (deps.onExternal) {
54+
void deps
55+
.onExternal(event)
56+
.catch((error) => deps.logger.error("external.dispatch_failed", { error: String(error) }));
57+
}
5458
return true;
5559
}
5660
const type = event.eventType ?? inferType(event.body);

tests/gateway/dispatch.test.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,14 @@ describe("dispatchEvent sender agent identity", () => {
435435
});
436436

437437
describe("dispatchEvent external providers", () => {
438-
it("hands a non-inkbox event to onExternal and acks", async () => {
439-
const onExternal = vi.fn(async () => {});
438+
it("hands a non-inkbox event to onExternal and acks without waiting for the turn", async () => {
439+
let finish: () => void = () => {};
440+
const onExternal = vi.fn(
441+
() =>
442+
new Promise<void>((resolve) => {
443+
finish = resolve;
444+
}),
445+
);
440446
const deps = makeDeps({ onExternal });
441447
const external: VerifiedEvent = {
442448
provider: "github",
@@ -451,6 +457,28 @@ describe("dispatchEvent external providers", () => {
451457
expect(ok).toBe(true);
452458
expect(onExternal).toHaveBeenCalledWith(external);
453459
expect(deps.sessions.handleInbound).not.toHaveBeenCalled();
460+
finish();
461+
});
462+
463+
it("logs an external turn rejected after acknowledgement", async () => {
464+
const onExternal = vi.fn(async () => {
465+
throw new Error("capture failed");
466+
});
467+
const deps = makeDeps({ onExternal });
468+
const external: VerifiedEvent = {
469+
provider: "github",
470+
verified: true,
471+
eventType: "push",
472+
body: { ref: "refs/heads/main" },
473+
headers: {},
474+
};
475+
476+
await expect(dispatchEvent(deps, external)).resolves.toBe(true);
477+
await vi.waitFor(() =>
478+
expect(deps.logger.error).toHaveBeenCalledWith("external.dispatch_failed", {
479+
error: "Error: capture failed",
480+
}),
481+
);
454482
});
455483
});
456484

tests/live/external-event.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function workflowRunBody(runId: string): string {
2525
name: "CI",
2626
event: "pull_request",
2727
status: "completed",
28-
conclusion: "failure",
28+
conclusion: "success",
2929
head_branch: "main",
3030
html_url: `https://github.com/${repository}/actions/runs/${runId}`,
3131
},

0 commit comments

Comments
 (0)