@remit/imap-worker 0.0.64 → 0.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/handlers/append-sent-message.ts +2 -15
- package/src/handlers/flag-push.ts +2 -16
- package/src/handlers/message-copy.ts +2 -16
- package/src/handlers/message-delete.ts +2 -16
- package/src/handlers/message-move.ts +2 -16
- package/src/handlers/placement-move-push.ts +2 -16
- package/src/handlers/sync-message-body.ts +2 -29
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
buildMailMessage,
|
|
11
11
|
renderRawMessage,
|
|
12
12
|
} from "@remit/smtp-service/message-builder";
|
|
13
|
+
import { attemptBudget } from "@remit/sqs-client/attempt-budget";
|
|
13
14
|
import { isAccountDeleted } from "../account-check.js";
|
|
14
15
|
import { createConnectionScopeWithCredentials } from "../connection-scope.js";
|
|
15
16
|
import type { AppendSentMessageEvent } from "../events.js";
|
|
@@ -29,23 +30,9 @@ const ROW_SURVIVED_ITS_DELETE =
|
|
|
29
30
|
const unfiledAppendRefused = (fullPath: string, error: unknown): string =>
|
|
30
31
|
`Sent, but not filed: the mail server refused to store a copy in ${fullPath} (${error instanceof Error ? error.message : String(error)}).`;
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
-
* Fallback when `APPEND_SENT_MAX_ATTEMPTS` is unset (local dev, unit tests).
|
|
34
|
-
* Matches the shared `MAX_RECEIVE_COUNT` every queue's redrive policy uses,
|
|
35
|
-
* same pattern as `FLAG_PUSH_MAX_ATTEMPTS` / `BODY_SYNC_MAX_ATTEMPTS`.
|
|
36
|
-
*/
|
|
37
|
-
const DEFAULT_APPEND_SENT_MAX_ATTEMPTS = 3;
|
|
38
|
-
|
|
39
33
|
export const getAppendSentMaxAttempts = (
|
|
40
34
|
processEnv: NodeJS.ProcessEnv = process.env,
|
|
41
|
-
): number =>
|
|
42
|
-
const raw = processEnv.APPEND_SENT_MAX_ATTEMPTS;
|
|
43
|
-
if (!raw) return DEFAULT_APPEND_SENT_MAX_ATTEMPTS;
|
|
44
|
-
const parsed = Number.parseInt(raw, 10);
|
|
45
|
-
return Number.isFinite(parsed) && parsed > 0
|
|
46
|
-
? parsed
|
|
47
|
-
: DEFAULT_APPEND_SENT_MAX_ATTEMPTS;
|
|
48
|
-
};
|
|
35
|
+
): number => attemptBudget("APPEND_SENT_MAX_ATTEMPTS", 3, processEnv);
|
|
49
36
|
|
|
50
37
|
export const APPEND_SENT_MAX_ATTEMPTS = getAppendSentMaxAttempts();
|
|
51
38
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
MailboxCursorPausedError,
|
|
9
9
|
resolveExhaustedFlagPushFailure,
|
|
10
10
|
} from "@remit/mailbox-service";
|
|
11
|
+
import { attemptBudget } from "@remit/sqs-client/attempt-budget";
|
|
11
12
|
import { isAccountDeleted } from "../account-check.js";
|
|
12
13
|
import { createConnectionScopeWithCredentials } from "../connection-scope.js";
|
|
13
14
|
import type { FlagPushEvent } from "../events.js";
|
|
@@ -15,24 +16,9 @@ import { isNotFoundError } from "../is-not-found.js";
|
|
|
15
16
|
import { withOAuthLifecycle } from "../with-oauth-lifecycle.js";
|
|
16
17
|
import { buildLifecycleDeps } from "../with-oauth-lifecycle-deps.js";
|
|
17
18
|
|
|
18
|
-
/**
|
|
19
|
-
* Fallback when `FLAG_PUSH_MAX_ATTEMPTS` is unset (local dev, unit tests).
|
|
20
|
-
* Matches the shared `MAX_RECEIVE_COUNT` every queue's redrive policy uses
|
|
21
|
-
* (`infra/stacks/dev/stacks/remit-queue-stack.ts`), same pattern as
|
|
22
|
-
* `BODY_SYNC_MAX_ATTEMPTS` (#1270) / `PLACEMENT_MOVE_MAX_ATTEMPTS` (#1289).
|
|
23
|
-
*/
|
|
24
|
-
const DEFAULT_FLAG_PUSH_MAX_ATTEMPTS = 3;
|
|
25
|
-
|
|
26
19
|
export const getFlagPushMaxAttempts = (
|
|
27
20
|
processEnv: NodeJS.ProcessEnv = process.env,
|
|
28
|
-
): number =>
|
|
29
|
-
const raw = processEnv.FLAG_PUSH_MAX_ATTEMPTS;
|
|
30
|
-
if (!raw) return DEFAULT_FLAG_PUSH_MAX_ATTEMPTS;
|
|
31
|
-
const parsed = Number.parseInt(raw, 10);
|
|
32
|
-
return Number.isFinite(parsed) && parsed > 0
|
|
33
|
-
? parsed
|
|
34
|
-
: DEFAULT_FLAG_PUSH_MAX_ATTEMPTS;
|
|
35
|
-
};
|
|
21
|
+
): number => attemptBudget("FLAG_PUSH_MAX_ATTEMPTS", 3, processEnv);
|
|
36
22
|
|
|
37
23
|
export const FLAG_PUSH_MAX_ATTEMPTS = getFlagPushMaxAttempts();
|
|
38
24
|
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
MailboxCursorPausedError,
|
|
10
10
|
reconcileStaleMessage,
|
|
11
11
|
} from "@remit/mailbox-service";
|
|
12
|
+
import { attemptBudget } from "@remit/sqs-client/attempt-budget";
|
|
12
13
|
import { isAccountDeleted } from "../account-check.js";
|
|
13
14
|
import { createConnectionScopeWithCredentials } from "../connection-scope.js";
|
|
14
15
|
import type { MessageCopyEvent } from "../events.js";
|
|
@@ -31,24 +32,9 @@ const defaultDeps: MessageCopyDeps = {
|
|
|
31
32
|
createConnectionScope: createConnectionScopeWithCredentials,
|
|
32
33
|
};
|
|
33
34
|
|
|
34
|
-
/**
|
|
35
|
-
* Fallback when `MESSAGE_COPY_MAX_ATTEMPTS` is unset (local dev, unit tests).
|
|
36
|
-
* Matches the `maxReceiveCount` the message queue's redrive policy uses
|
|
37
|
-
* (`remit-messages.fifo`, `deploy/vps/queues.json`), same pattern as
|
|
38
|
-
* `MESSAGE_MOVE_MAX_ATTEMPTS`.
|
|
39
|
-
*/
|
|
40
|
-
const DEFAULT_MESSAGE_COPY_MAX_ATTEMPTS = 3;
|
|
41
|
-
|
|
42
35
|
export const getMessageCopyMaxAttempts = (
|
|
43
36
|
processEnv: NodeJS.ProcessEnv = process.env,
|
|
44
|
-
): number =>
|
|
45
|
-
const raw = processEnv.MESSAGE_COPY_MAX_ATTEMPTS;
|
|
46
|
-
if (!raw) return DEFAULT_MESSAGE_COPY_MAX_ATTEMPTS;
|
|
47
|
-
const parsed = Number.parseInt(raw, 10);
|
|
48
|
-
return Number.isFinite(parsed) && parsed > 0
|
|
49
|
-
? parsed
|
|
50
|
-
: DEFAULT_MESSAGE_COPY_MAX_ATTEMPTS;
|
|
51
|
-
};
|
|
37
|
+
): number => attemptBudget("MESSAGE_COPY_MAX_ATTEMPTS", 3, processEnv);
|
|
52
38
|
|
|
53
39
|
export const MESSAGE_COPY_MAX_ATTEMPTS = getMessageCopyMaxAttempts();
|
|
54
40
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
isMessageGoneFromOpenMailbox,
|
|
15
15
|
MailboxCursorPausedError,
|
|
16
16
|
} from "@remit/mailbox-service";
|
|
17
|
+
import { attemptBudget } from "@remit/sqs-client/attempt-budget";
|
|
17
18
|
import { isAccountDeleted } from "../account-check.js";
|
|
18
19
|
import { createConnectionScopeWithCredentials } from "../connection-scope.js";
|
|
19
20
|
import { emitEvent } from "../emit.js";
|
|
@@ -28,24 +29,9 @@ import {
|
|
|
28
29
|
buildThreadMessageTrashUpdate,
|
|
29
30
|
} from "./thread-message-rows.js";
|
|
30
31
|
|
|
31
|
-
/**
|
|
32
|
-
* Fallback when `MESSAGE_DELETE_MAX_ATTEMPTS` is unset (local dev, unit tests).
|
|
33
|
-
* Matches the `maxReceiveCount` the redrive policy of the queue `emit.ts`
|
|
34
|
-
* routes MESSAGE_DELETE onto uses (`remit-message-mgmt`,
|
|
35
|
-
* `deploy/vps/queues.json`), same pattern as `MESSAGE_MOVE_MAX_ATTEMPTS`.
|
|
36
|
-
*/
|
|
37
|
-
const DEFAULT_MESSAGE_DELETE_MAX_ATTEMPTS = 3;
|
|
38
|
-
|
|
39
32
|
export const getMessageDeleteMaxAttempts = (
|
|
40
33
|
processEnv: NodeJS.ProcessEnv = process.env,
|
|
41
|
-
): number =>
|
|
42
|
-
const raw = processEnv.MESSAGE_DELETE_MAX_ATTEMPTS;
|
|
43
|
-
if (!raw) return DEFAULT_MESSAGE_DELETE_MAX_ATTEMPTS;
|
|
44
|
-
const parsed = Number.parseInt(raw, 10);
|
|
45
|
-
return Number.isFinite(parsed) && parsed > 0
|
|
46
|
-
? parsed
|
|
47
|
-
: DEFAULT_MESSAGE_DELETE_MAX_ATTEMPTS;
|
|
48
|
-
};
|
|
34
|
+
): number => attemptBudget("MESSAGE_DELETE_MAX_ATTEMPTS", 3, processEnv);
|
|
49
35
|
|
|
50
36
|
export const MESSAGE_DELETE_MAX_ATTEMPTS = getMessageDeleteMaxAttempts();
|
|
51
37
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
isPlacementUnsettled,
|
|
11
11
|
MailboxCursorPausedError,
|
|
12
12
|
} from "@remit/mailbox-service";
|
|
13
|
+
import { attemptBudget } from "@remit/sqs-client/attempt-budget";
|
|
13
14
|
import { isAccountDeleted } from "../account-check.js";
|
|
14
15
|
import { createConnectionScopeWithCredentials } from "../connection-scope.js";
|
|
15
16
|
import { emitEvent } from "../emit.js";
|
|
@@ -19,24 +20,9 @@ import { withOAuthLifecycle } from "../with-oauth-lifecycle.js";
|
|
|
19
20
|
import { buildLifecycleDeps } from "../with-oauth-lifecycle-deps.js";
|
|
20
21
|
import { resolveExhaustedMessageMoveFailure } from "./message-move-terminal.js";
|
|
21
22
|
|
|
22
|
-
/**
|
|
23
|
-
* Fallback when `MESSAGE_MOVE_MAX_ATTEMPTS` is unset (local dev, unit tests).
|
|
24
|
-
* Matches the `maxReceiveCount` the message queue's redrive policy uses
|
|
25
|
-
* (`remit-messages.fifo`, `deploy/vps/queues.json`), same pattern as
|
|
26
|
-
* `FLAG_PUSH_MAX_ATTEMPTS` and `PLACEMENT_MOVE_MAX_ATTEMPTS`.
|
|
27
|
-
*/
|
|
28
|
-
const DEFAULT_MESSAGE_MOVE_MAX_ATTEMPTS = 3;
|
|
29
|
-
|
|
30
23
|
export const getMessageMoveMaxAttempts = (
|
|
31
24
|
processEnv: NodeJS.ProcessEnv = process.env,
|
|
32
|
-
): number =>
|
|
33
|
-
const raw = processEnv.MESSAGE_MOVE_MAX_ATTEMPTS;
|
|
34
|
-
if (!raw) return DEFAULT_MESSAGE_MOVE_MAX_ATTEMPTS;
|
|
35
|
-
const parsed = Number.parseInt(raw, 10);
|
|
36
|
-
return Number.isFinite(parsed) && parsed > 0
|
|
37
|
-
? parsed
|
|
38
|
-
: DEFAULT_MESSAGE_MOVE_MAX_ATTEMPTS;
|
|
39
|
-
};
|
|
25
|
+
): number => attemptBudget("MESSAGE_MOVE_MAX_ATTEMPTS", 3, processEnv);
|
|
40
26
|
|
|
41
27
|
export const MESSAGE_MOVE_MAX_ATTEMPTS = getMessageMoveMaxAttempts();
|
|
42
28
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
reconcileStaleMessage,
|
|
11
11
|
resolveExhaustedPlacementMoveFailure,
|
|
12
12
|
} from "@remit/mailbox-service";
|
|
13
|
+
import { attemptBudget } from "@remit/sqs-client/attempt-budget";
|
|
13
14
|
import { isAccountDeleted } from "../account-check.js";
|
|
14
15
|
import { createConnectionScopeWithCredentials } from "../connection-scope.js";
|
|
15
16
|
import { emitEvent } from "../emit.js";
|
|
@@ -23,24 +24,9 @@ import {
|
|
|
23
24
|
searchMailboxByMessageId,
|
|
24
25
|
} from "./message-move.js";
|
|
25
26
|
|
|
26
|
-
/**
|
|
27
|
-
* Fallback when `PLACEMENT_MOVE_MAX_ATTEMPTS` is unset (local dev, unit
|
|
28
|
-
* tests). Matches the placement-move queue's own `MAX_RECEIVE_COUNT` default
|
|
29
|
-
* (`infra/stacks/dev/stacks/remit-queue-stack.ts`), same pattern as
|
|
30
|
-
* `BODY_SYNC_MAX_ATTEMPTS` (#1270).
|
|
31
|
-
*/
|
|
32
|
-
const DEFAULT_PLACEMENT_MOVE_MAX_ATTEMPTS = 3;
|
|
33
|
-
|
|
34
27
|
export const getPlacementMoveMaxAttempts = (
|
|
35
28
|
processEnv: NodeJS.ProcessEnv = process.env,
|
|
36
|
-
): number =>
|
|
37
|
-
const raw = processEnv.PLACEMENT_MOVE_MAX_ATTEMPTS;
|
|
38
|
-
if (!raw) return DEFAULT_PLACEMENT_MOVE_MAX_ATTEMPTS;
|
|
39
|
-
const parsed = Number.parseInt(raw, 10);
|
|
40
|
-
return Number.isFinite(parsed) && parsed > 0
|
|
41
|
-
? parsed
|
|
42
|
-
: DEFAULT_PLACEMENT_MOVE_MAX_ATTEMPTS;
|
|
43
|
-
};
|
|
29
|
+
): number => attemptBudget("PLACEMENT_MOVE_MAX_ATTEMPTS", 3, processEnv);
|
|
44
30
|
|
|
45
31
|
export const PLACEMENT_MOVE_MAX_ATTEMPTS = getPlacementMoveMaxAttempts();
|
|
46
32
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
QuarantineService,
|
|
12
12
|
resolveExhaustedBodySyncFailures,
|
|
13
13
|
} from "@remit/mailbox-service";
|
|
14
|
+
import { attemptBudget } from "@remit/sqs-client/attempt-budget";
|
|
14
15
|
import { env } from "expect-env";
|
|
15
16
|
import { isAccountDeleted } from "../account-check.js";
|
|
16
17
|
import { isBodySyncEnabled } from "../body-sync-gate.js";
|
|
@@ -27,37 +28,9 @@ import { workerVersion } from "../worker-version.js";
|
|
|
27
28
|
|
|
28
29
|
const bodySyncEnabledParameterName = env.BODY_SYNC_ENABLED_PARAMETER_NAME;
|
|
29
30
|
|
|
30
|
-
/**
|
|
31
|
-
* Fallback when `BODY_SYNC_MAX_ATTEMPTS` is unset (local dev, unit tests).
|
|
32
|
-
* Matches the body queue's own `MAX_RECEIVE_COUNT` default
|
|
33
|
-
* (`infra/stacks/dev/stacks/remit-queue-stack.ts`) so an environment that
|
|
34
|
-
* never injects the var still behaves like production.
|
|
35
|
-
*/
|
|
36
|
-
const DEFAULT_BODY_SYNC_MAX_ATTEMPTS = 3;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Reads the redelivery-budget-exhaustion threshold. CDK derives
|
|
40
|
-
* `BODY_SYNC_MAX_ATTEMPTS` from the body queue's own `MAX_RECEIVE_COUNT`
|
|
41
|
-
* (`remit-worker-stack.ts`) so the two constants can't drift apart — a
|
|
42
|
-
* hand-copied duplicate here previously risked the worker resolving
|
|
43
|
-
* "last attempt" on a different delivery than the queue's redrive policy
|
|
44
|
-
* actually uses (issue #1270). SQS's own `ApproximateReceiveCount` is the
|
|
45
|
-
* source of truth for how many times a record has been delivered; once it
|
|
46
|
-
* reaches this value, the current invocation is the last attempt before the
|
|
47
|
-
* queue's own redrive would DLQ the record, so retry exhaustion is resolved
|
|
48
|
-
* here (see `resolveExhaustedBodySyncFailures`) instead of letting the
|
|
49
|
-
* record dead-letter with no diagnosis.
|
|
50
|
-
*/
|
|
51
31
|
export const getBodySyncMaxAttempts = (
|
|
52
32
|
processEnv: NodeJS.ProcessEnv = process.env,
|
|
53
|
-
): number =>
|
|
54
|
-
const raw = processEnv.BODY_SYNC_MAX_ATTEMPTS;
|
|
55
|
-
if (!raw) return DEFAULT_BODY_SYNC_MAX_ATTEMPTS;
|
|
56
|
-
const parsed = Number.parseInt(raw, 10);
|
|
57
|
-
return Number.isFinite(parsed) && parsed > 0
|
|
58
|
-
? parsed
|
|
59
|
-
: DEFAULT_BODY_SYNC_MAX_ATTEMPTS;
|
|
60
|
-
};
|
|
33
|
+
): number => attemptBudget("BODY_SYNC_MAX_ATTEMPTS", 3, processEnv);
|
|
61
34
|
|
|
62
35
|
export const BODY_SYNC_MAX_ATTEMPTS = getBodySyncMaxAttempts();
|
|
63
36
|
|