Skip to content
Merged
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
12 changes: 11 additions & 1 deletion src/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,17 @@ First return your data from `external` and then resume update handling using `wa
const ret = await this.escape((ctx) => task(ctx));
return { ok: true, ret: await beforeStore(ret) } as const;
} catch (e) {
return { ok: false, err: await beforeStoreError(e) } as const;
try {
return {
ok: false,
err: await beforeStoreError(e),
} as const;
} catch (e) {
return {
ok: false,
err: `Error in beforeStoreError, failed to serialize: ${e}`,
} as const;
}
} finally {
this.insideExternal = false;
}
Expand Down
35 changes: 34 additions & 1 deletion test/conversation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
assertSpyCall,
assertSpyCalls,
assertStrictEquals,
assertStringIncludes,
assertThrows,
describe,
it,
Expand Down Expand Up @@ -244,7 +245,7 @@ describe("Conversation", () => {
assertEquals(ctx.update, { update_id: rnd });
assertEquals(i, 1);
});
it("should support throw an error when outside context objects are used in external after advancing from an event", async () => {
it("should throw an error when outside context objects are used in external after advancing from an event", async () => {
const ctx = mkctx({ update_id: Math.random() });
let i = 0;
let rnd = 0;
Expand Down Expand Up @@ -307,6 +308,38 @@ describe("Conversation", () => {
assert(second.status === "complete");
assertEquals(i, 1);
});
it("should support external with error handling for bad error serialisation", async () => {
const ctx = mkctx();
let i = 0;
let j = 0;
async function convo(conversation: Convo) {
try {
await conversation.external({
task: () => {
throw new Error("trigger");
},
beforeStoreError: () => {
throw new Error("meh");
},
});
j++;
} catch (e) {
assert(typeof e === "string");
assertStringIncludes(e, "failed to serialize");
}
await conversation.wait();
i++;
}
const first = await enterConversation(convo, ctx);
assertEquals(first.status, "handled");
assert(first.status === "handled");
const copy = structuredClone(first);
const second = await resumeConversation(convo, ctx, copy);
assertEquals(second.status, "complete");
assert(second.status === "complete");
assertEquals(i, 1);
assertEquals(j, 0);
});
it("should support external with custom error formats", async () => {
const ctx = mkctx();
let i = 0;
Expand Down