@remit/imap-worker 0.0.31 → 0.0.33
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
CHANGED
|
@@ -106,6 +106,10 @@ const deps = (): MailboxManagementDeps =>
|
|
|
106
106
|
h.calls.push({ method: "mailbox.update", args });
|
|
107
107
|
if (h.mailboxUpdateError) throw h.mailboxUpdateError;
|
|
108
108
|
},
|
|
109
|
+
findByPathPrefix: async (...args: unknown[]) => {
|
|
110
|
+
h.calls.push({ method: "mailbox.findByPathPrefix", args });
|
|
111
|
+
return [];
|
|
112
|
+
},
|
|
109
113
|
delete: record("mailbox.delete"),
|
|
110
114
|
},
|
|
111
115
|
secrets: {},
|
|
@@ -70,15 +70,18 @@ const isMailboxPresentUpstream = (error: unknown): boolean => {
|
|
|
70
70
|
* Pinned invariant for the whole-chain terminal guards below.
|
|
71
71
|
*
|
|
72
72
|
* Each handler wraps its `MailboxManagementService.sync*` chain in a try/catch
|
|
73
|
-
* that treats a NotFoundError as terminal (ack with a WARN, issue #289). That
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
73
|
+
* that treats a NotFoundError as terminal (ack with a WARN, issue #289). That is
|
|
74
|
+
* only sound while the sole row a NotFoundError can refer to is the target
|
|
75
|
+
* mailbox, so its absence can only mean the user deleted the folder mid-sync —
|
|
76
|
+
* never an unrelated missing entity that should have been retried.
|
|
77
|
+
*
|
|
78
|
+
* `syncCreate` and `syncDelete` hold to that by touching nothing but the target
|
|
79
|
+
* row. `syncRename` also writes the renamed subtree's descendant rows, and keeps
|
|
80
|
+
* the invariant by absorbing their NotFoundErrors itself: a descendant deleted
|
|
81
|
+
* mid-settle never reaches these catches. Any sync method that reads or writes a
|
|
82
|
+
* second entity owes the same, or these catches must be narrowed (match the
|
|
83
|
+
* mailboxId / re-check existence) before a NotFoundError from elsewhere is
|
|
84
|
+
* silently acked.
|
|
82
85
|
*/
|
|
83
86
|
|
|
84
87
|
/**
|
package/src/scheduler/config.ts
CHANGED
|
@@ -6,15 +6,20 @@
|
|
|
6
6
|
* in remit-account-worker/src/config.ts).
|
|
7
7
|
*
|
|
8
8
|
* `tickIntervalSeconds` drives how often the tick itself runs — the
|
|
9
|
-
* EventBridge schedule rate
|
|
10
|
-
* must stay well below `offlineIntervalSeconds` so a tick
|
|
11
|
-
* every account crossing the threshold. CDK and this runtime
|
|
12
|
-
* agree — see infra/lib/config.ts's `mailboxSync` stage config.
|
|
9
|
+
* EventBridge schedule rate on a managed deployment, the runner's loop delay
|
|
10
|
+
* everywhere else — and must stay well below `offlineIntervalSeconds` so a tick
|
|
11
|
+
* reliably observes every account crossing the threshold. CDK and this runtime
|
|
12
|
+
* default must agree — see infra/lib/config.ts's `mailboxSync` stage config.
|
|
13
13
|
*
|
|
14
14
|
* `offlineIntervalSeconds` is the only due-ness threshold: an account is due
|
|
15
15
|
* once its last successful sync is older than this interval. There is no
|
|
16
16
|
* "online" tier — client-side polling (useStaleAccountSync) covers an
|
|
17
17
|
* account while its mail is actively open in the web client.
|
|
18
|
+
*
|
|
19
|
+
* The defaults below are a floor for a deployment that sets neither. The
|
|
20
|
+
* standalone stack sets both, at a cadence sized for one box and a handful of
|
|
21
|
+
* accounts, and the checker's stall threshold is derived from those values —
|
|
22
|
+
* see deploy/vps/docker-compose.sqlite.yml's `scheduler` service.
|
|
18
23
|
*/
|
|
19
24
|
|
|
20
25
|
const DEFAULT_TICK_INTERVAL_SECONDS = 60 * 60; // 1 hour
|
package/src/scheduler/handler.ts
CHANGED
|
@@ -16,8 +16,8 @@ const sqsClient = createQueueProducer({ queueUrl: mailboxesQueueUrl });
|
|
|
16
16
|
* (#1247, restructured #1251). Ticks at `MAILBOX_SYNC_TICK_INTERVAL_SECONDS`
|
|
17
17
|
* (rate schedule, wired in infra/stacks/dev/stacks/remit-worker-stack.ts) and
|
|
18
18
|
* delegates the actual decision + enqueue to `runSchedulerTick` — the same
|
|
19
|
-
* function the
|
|
20
|
-
*
|
|
19
|
+
* function the timer loop calls on a deployment with no EventBridge (see
|
|
20
|
+
* `runner.ts`), so every deployment runs one code path.
|
|
21
21
|
*
|
|
22
22
|
* Uses the EventBridge event's own `time` (the scheduled fire time) as the
|
|
23
23
|
* tick's `now`, rather than `Date.now()` at processing time. This is what
|
|
@@ -8,18 +8,15 @@ import { getOfflineIntervalMs, getTickIntervalMs } from "./config.js";
|
|
|
8
8
|
import { runSchedulerTick } from "./run-tick.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* `MAILBOX_SYNC_TICK_INTERVAL_SECONDS` cadence
|
|
16
|
-
*
|
|
17
|
-
* own scheduling logic.
|
|
11
|
+
* The scheduled-sync runner for every deployment that has no EventBridge: the
|
|
12
|
+
* self-host stack's `scheduler` service and the local dev compose stack. A
|
|
13
|
+
* managed deployment fires `runSchedulerTick` off an EventBridge schedule (see
|
|
14
|
+
* handler.ts); this process ticks the same function on a plain loop at the same
|
|
15
|
+
* `MAILBOX_SYNC_TICK_INTERVAL_SECONDS` cadence, so there is one scheduling
|
|
16
|
+
* implementation and one set of knobs.
|
|
18
17
|
*
|
|
19
|
-
*
|
|
20
|
-
* `
|
|
21
|
-
* than swallowing it — docker-compose's `restart: unless-stopped` brings it
|
|
22
|
-
* back for the next tick.
|
|
18
|
+
* A tick failure crashes the process loudly rather than being swallowed —
|
|
19
|
+
* compose's `restart: unless-stopped` brings it back for the next tick.
|
|
23
20
|
*/
|
|
24
21
|
|
|
25
22
|
const log = createLogger();
|
|
@@ -40,7 +37,7 @@ const CRASH_BACKOFF_MS = 5_000;
|
|
|
40
37
|
|
|
41
38
|
log.info(
|
|
42
39
|
{ tickIntervalMs, offlineIntervalMs },
|
|
43
|
-
"
|
|
40
|
+
"Scheduled-sync runner started",
|
|
44
41
|
);
|
|
45
42
|
|
|
46
43
|
const runLoop = async (): Promise<void> => {
|