@@ -9,6 +9,12 @@ import type {
99 ChannelMessageUnknownSendReconciliationResult ,
1010} from "../../channels/message/types.js" ;
1111import type { OpenClawConfig } from "../../config/types.openclaw.js" ;
12+ import {
13+ claimRecoveryEntry as claimSharedRecoveryEntry ,
14+ computeBackoffMs ,
15+ getErrnoCode ,
16+ releaseRecoveryEntry as releaseSharedRecoveryEntry ,
17+ } from "../delivery-recovery.shared.js" ;
1218import { formatErrorMessage } from "../errors.js" ;
1319import { resolveOutboundChannelMessageAdapter } from "./channel-resolution.js" ;
1420import type { OutboundDeliveryResult } from "./deliver-types.js" ;
@@ -26,6 +32,8 @@ import {
2632 type QueuedDeliveryPayload ,
2733} from "./delivery-queue-storage.js" ;
2834
35+ export { computeBackoffMs } ;
36+
2937export type RecoverySummary = {
3038 recovered : number ;
3139 failed : number ;
@@ -61,14 +69,6 @@ export type ActiveDeliveryClaimResult<T> =
6169
6270const MAX_RETRIES = 5 ;
6371
64- /** Backoff delays in milliseconds indexed by retry count (1-based). */
65- const BACKOFF_MS : readonly number [ ] = [
66- 5_000 , // retry 1: 5s
67- 25_000 , // retry 2: 25s
68- 120_000 , // retry 3: 2m
69- 600_000 , // retry 4: 10m
70- ] ;
71-
7272const PERMANENT_ERROR_PATTERNS : readonly RegExp [ ] = [
7373 / n o c o n v e r s a t i o n r e f e r e n c e f o u n d / i,
7474 / c h a t n o t f o u n d / i,
@@ -97,12 +97,6 @@ function resolveRecoveryDeadlineMs(maxRecoveryMs: number | undefined): number {
9797 return resolveExpiresAtMsFromDurationMs ( durationMs ) ?? resolveDateTimestampMs ( Date . now ( ) ) ;
9898}
9999
100- function getErrnoCode ( err : unknown ) : string | null {
101- return err && typeof err === "object" && "code" in err
102- ? String ( ( err as { code ?: unknown } ) . code )
103- : null ;
104- }
105-
106100function createEmptyRecoverySummary ( ) : RecoverySummary {
107101 return {
108102 recovered : 0 ,
@@ -112,30 +106,18 @@ function createEmptyRecoverySummary(): RecoverySummary {
112106 } ;
113107}
114108
115- function claimRecoveryEntry ( entryId : string ) : boolean {
116- if ( entriesInProgress . has ( entryId ) ) {
117- return false ;
118- }
119- entriesInProgress . add ( entryId ) ;
120- return true ;
121- }
122-
123- function releaseRecoveryEntry ( entryId : string ) : void {
124- entriesInProgress . delete ( entryId ) ;
125- }
126-
127109export async function withActiveDeliveryClaim < T > (
128110 entryId : string ,
129111 fn : ( ) => Promise < T > ,
130112) : Promise < ActiveDeliveryClaimResult < T > > {
131- if ( ! claimRecoveryEntry ( entryId ) ) {
113+ if ( ! claimSharedRecoveryEntry ( entriesInProgress , entryId ) ) {
132114 return { status : "claimed-by-other-owner" } ;
133115 }
134116
135117 try {
136118 return { status : "claimed" , value : await fn ( ) } ;
137119 } finally {
138- releaseRecoveryEntry ( entryId ) ;
120+ releaseSharedRecoveryEntry ( entriesInProgress , entryId ) ;
139121 }
140122}
141123
@@ -326,14 +308,6 @@ async function moveEntryToFailedWithLogging(
326308 }
327309}
328310
329- /** Compute the backoff delay in ms for a given retry count. */
330- export function computeBackoffMs ( retryCount : number ) : number {
331- if ( retryCount <= 0 ) {
332- return 0 ;
333- }
334- return BACKOFF_MS [ Math . min ( retryCount - 1 , BACKOFF_MS . length - 1 ) ] ?? BACKOFF_MS . at ( - 1 ) ?? 0 ;
335- }
336-
337311export function isEntryEligibleForRecoveryRetry (
338312 entry : QueuedDelivery ,
339313 now : number ,
@@ -513,7 +487,7 @@ export async function drainPendingDeliveries(opts: {
513487 ) ;
514488
515489 for ( const entry of matchingEntries ) {
516- if ( ! claimRecoveryEntry ( entry . id ) ) {
490+ if ( ! claimSharedRecoveryEntry ( entriesInProgress , entry . id ) ) {
517491 opts . log . info ( `${ opts . logLabel } : entry ${ entry . id } is already being recovered` ) ;
518492 continue ;
519493 }
@@ -582,7 +556,7 @@ export async function drainPendingDeliveries(opts: {
582556 ) ;
583557 }
584558 } finally {
585- releaseRecoveryEntry ( entry . id ) ;
559+ releaseSharedRecoveryEntry ( entriesInProgress , entry . id ) ;
586560 }
587561 }
588562 } finally {
@@ -622,7 +596,7 @@ export async function recoverPendingDeliveries(opts: {
622596 break ;
623597 }
624598
625- if ( ! claimRecoveryEntry ( entry . id ) ) {
599+ if ( ! claimSharedRecoveryEntry ( entriesInProgress , entry . id ) ) {
626600 opts . log . info ( `Recovery skipped for delivery ${ entry . id } : already being processed` ) ;
627601 continue ;
628602 }
@@ -677,7 +651,7 @@ export async function recoverPendingDeliveries(opts: {
677651 continue ;
678652 }
679653 } finally {
680- releaseRecoveryEntry ( entry . id ) ;
654+ releaseSharedRecoveryEntry ( entriesInProgress , entry . id ) ;
681655 }
682656 }
683657
0 commit comments