mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-30 13:20:54 +01:00
test(server): retain voice reply recovery after failed state reads
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
fe5e251319
commit
439d0a86eb
3 files changed
+33
No files matched your search
@@ -1255,3 +1255,13 @@ was stopped after repeated embedded PostgreSQL setup failures, not counted as a
|
||||
pass. Slice 22 owns voice reply delivery and begins with the multipart/outcome
|
||||
policy and publication-settlement producer audit. See
|
||||
[reply delivery audit](2026-10-25-voice-reply-delivery-sleep-audit.md).
|
||||
|
||||
Slice 22 now implements voice reply delivery from committed changes and saved
|
||||
retry/dispatch deadlines. The periodic reply scan and pre-publication direct push
|
||||
are removed. Real normal/operator publication tests prove the final-commit wake;
|
||||
turning that notification off reproduces zero delivered replies. The branch has
|
||||
786 selected passing tests across isolated voice, recovery, startup, and shared
|
||||
consumers, plus workspace typecheck/build. See the reply audit for retained
|
||||
fixture failures and local full-suite infrastructure limitations. Publication and
|
||||
latest-head review/check acceptance remain outstanding. Inbound admission cleanup,
|
||||
inbound history retention, and call reports remain separate next slices.
|
||||
@@ -194,3 +194,12 @@ PR CI/reviews remain required. The local all-suite command has the previously
|
||||
recorded embedded-PostgreSQL initialization limitation; targeted database suites
|
||||
run on real isolated PostgreSQL instead. Do not count skipped or uninitialized
|
||||
database tests as passes.
|
||||
|
||||
The parent recovery suite passed all 11 tests on its isolated database. The new
|
||||
reply-state read failure case also passed: the worker keeps its retry, performs
|
||||
no SQL during backoff, and sends once after recovery. Together with the full run,
|
||||
this verifies 108 voice cases, 16 startup cases, 11 parent recovery cases, and 651
|
||||
shared-consumer cases (786 selected tests). Workspace typecheck and build passed.
|
||||
The final added failure case changed tests only after the typecheck; the workspace
|
||||
build compiled the current tree. No production changes followed the full run.
|
||||
Remote CI/review remains pending until this branch is published.
|
||||
@@ -865,6 +865,20 @@ const support = external ? { supported: true } : await getEmbeddedPostgresTestSu
|
||||
expect(f.transport.sendCallMessage).not.toHaveBeenCalled(); await worker.quiet(); expect(worker.onError).not.toHaveBeenCalled();
|
||||
} finally { await worker.coordinator.stop(); vi.useRealTimers(); }
|
||||
});
|
||||
it("retains phone reply work after a failed state read and retries without intervening scans", async () => {
|
||||
const f = await pushFixture();
|
||||
vi.useFakeTimers({ toFake: ["Date", "setTimeout", "clearTimeout"], shouldAdvanceTime: true });
|
||||
const transaction = vi.spyOn(db, "transaction").mockRejectedValueOnce(new Error("reply database unavailable"));
|
||||
const worker = await replyWorker(f);
|
||||
transaction.mockRestore();
|
||||
try {
|
||||
expect(worker.onError).toHaveBeenCalledOnce(); expect(f.transport.sendCallMessage).not.toHaveBeenCalled();
|
||||
const retryAt = worker.coordinator.nextWakeAt()!;
|
||||
expect(retryAt).toBeGreaterThan(Date.now() + 20_000); await worker.quiet(10_000);
|
||||
await vi.advanceTimersByTimeAsync(retryAt - Date.now()); await worker.settled();
|
||||
expect(f.transport.sendCallMessage).toHaveBeenCalledOnce(); expect(worker.onError).toHaveBeenCalledOnce(); await worker.quiet();
|
||||
} finally { transaction.mockRestore(); await worker.coordinator.stop(); vi.useRealTimers(); }
|
||||
});
|
||||
it("notifies phone questions once and waits for authorized retrieval before later answers", async () => {
|
||||
const f = await pushFixture(), interactionId = randomUUID();
|
||||
await db.insert(issueThreadInteractions).values({id: interactionId, companyId: f.companyId, issueId: f.issueId, kind: "ask_user_questions", status: "pending", addresseeUserId: f.callerId, effectiveResolverPolicy: "addressee_only", payload: {version: 1, questions: [{id: "color", prompt: "Which color?", selectionMode: "single", required: true, options: [{id: "cobalt", label: "Cobalt"}]}]}});
|
||||
|
||||
Reference in new issue
Block a user