fix(cron): stop retrying permanent delivery rejection (#122821)

This commit is contained in:
Peter Steinberger
2026-08-12 14:32:11 -07:00
committed by GitHub
parent c58dbaff22
commit 431b8ec4a4
2 changed files with 24 additions and 2 deletions
@@ -15,7 +15,7 @@ import {
loadDeliveryQueueEntry,
type DeliveryQueueCompletionRetention,
} from "../../infra/delivery-queue-sqlite.js";
import { isProvenDeliveryNotSentError } from "../../infra/delivery-recovery.shared.js";
import * as deliveryRecovery from "../../infra/delivery-recovery.shared.js";
import { isFastTestRuntimeEnv } from "../../infra/env.js";
import { OUTBOUND_DELIVERY_QUEUE_NAME } from "../../infra/outbound/delivery-queue-media-staging.js";
import { normalizeTargetForProvider } from "../../infra/outbound/target-normalization.js";
@@ -254,6 +254,9 @@ function summarizeDirectCronDeliveryError(error: unknown): string {
}
function isTransientDirectCronDeliveryError(error: unknown): boolean {
if (deliveryRecovery.findPlatformMessageRejectedError(error)) {
return false;
}
const message = summarizeDirectCronDeliveryError(error);
if (!message) {
return false;
@@ -261,7 +264,7 @@ function isTransientDirectCronDeliveryError(error: unknown): boolean {
if (PERMANENT_DIRECT_CRON_DELIVERY_ERROR_PATTERNS.some((re) => re.test(message))) {
return false;
}
return isProvenDeliveryNotSentError(error);
return deliveryRecovery.isProvenDeliveryNotSentError(error);
}
function resolveDirectCronRetryDelaysMs(): readonly number[] {
return isFastTestRuntimeEnv() ? [0, 0, 0] : [5_000, 10_000, 20_000];
@@ -2327,6 +2327,25 @@ describe("dispatchCronDelivery — double-announce guard", () => {
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(2);
});
it("does not retry permanent typed pre-dispatch rejections", async () => {
vi.stubEnv("OPENCLAW_TEST_FAST", "1");
const rejection = new PlatformMessageNotDispatchedError("payload rejected", {
cause: new Error("invalid payload"),
retryable: false,
});
vi.mocked(deliverOutboundPayloads).mockRejectedValue(rejection);
const params = makeBaseParams({ synthesizedText: "Reject this once." });
const state = await dispatchCronDelivery(params);
expect(deliverOutboundPayloads).toHaveBeenCalledTimes(1);
expectResultFields(state.result, {
status: "error",
error: String(rejection),
deliveryAttempted: true,
});
});
it.each(["structured", "threaded"] as const)(
"retries proven-not-sent %s cron delivery without duplicating a message",
async (deliveryKind) => {