@remit/imap-worker 0.0.90 → 0.0.91

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.
Files changed (172) hide show
  1. package/dist/account-check.d.ts +27 -0
  2. package/dist/account-check.js +70 -0
  3. package/dist/body-sync-gate.d.ts +12 -0
  4. package/dist/body-sync-gate.js +53 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +193 -0
  7. package/dist/config-env.d.ts +5 -0
  8. package/dist/config-env.js +37 -0
  9. package/dist/connection-pool.d.ts +22 -0
  10. package/dist/connection-pool.js +97 -0
  11. package/dist/connection-scope.d.ts +8 -0
  12. package/dist/connection-scope.js +10 -0
  13. package/dist/context.d.ts +46 -0
  14. package/dist/context.js +15 -0
  15. package/dist/e2e-processor-shim.d.ts +2 -0
  16. package/dist/e2e-processor-shim.js +181 -0
  17. package/dist/emit.d.ts +15 -0
  18. package/dist/emit.js +76 -0
  19. package/dist/events.d.ts +203 -0
  20. package/dist/events.js +1 -0
  21. package/dist/failure-kind.d.ts +10 -0
  22. package/{src/failure-kind.ts → dist/failure-kind.js} +6 -6
  23. package/dist/handlers/append-sent-message.d.ts +3 -0
  24. package/dist/handlers/append-sent-message.js +152 -0
  25. package/dist/handlers/delete-account-objects.d.ts +3 -0
  26. package/dist/handlers/delete-account-objects.js +35 -0
  27. package/dist/handlers/empty-trash.d.ts +14 -0
  28. package/dist/handlers/empty-trash.js +217 -0
  29. package/dist/handlers/flag-push.d.ts +38 -0
  30. package/dist/handlers/flag-push.js +195 -0
  31. package/dist/handlers/imported-folder.d.ts +4 -0
  32. package/dist/handlers/imported-folder.js +23 -0
  33. package/dist/handlers/mailbox-management.d.ts +6 -0
  34. package/dist/handlers/mailbox-management.js +294 -0
  35. package/dist/handlers/mailbox-sync-order.d.ts +21 -0
  36. package/dist/handlers/mailbox-sync-order.js +50 -0
  37. package/dist/handlers/message-copy.d.ts +40 -0
  38. package/dist/handlers/message-copy.js +371 -0
  39. package/dist/handlers/message-delete-terminal.d.ts +60 -0
  40. package/dist/handlers/message-delete-terminal.js +77 -0
  41. package/dist/handlers/message-delete.d.ts +57 -0
  42. package/dist/handlers/message-delete.js +520 -0
  43. package/{src/handlers/message-move-terminal.ts → dist/handlers/message-move-terminal.d.ts} +18 -105
  44. package/dist/handlers/message-move-terminal.js +94 -0
  45. package/dist/handlers/message-move.d.ts +146 -0
  46. package/dist/handlers/message-move.js +490 -0
  47. package/dist/handlers/placement-move-push.d.ts +62 -0
  48. package/dist/handlers/placement-move-push.js +307 -0
  49. package/dist/handlers/probe-message-id.d.ts +2 -0
  50. package/dist/handlers/probe-message-id.js +6 -0
  51. package/dist/handlers/sync-mailboxes.d.ts +45 -0
  52. package/dist/handlers/sync-mailboxes.js +233 -0
  53. package/dist/handlers/sync-message-body.d.ts +23 -0
  54. package/dist/handlers/sync-message-body.js +182 -0
  55. package/dist/handlers/sync-messages.d.ts +29 -0
  56. package/dist/handlers/sync-messages.js +285 -0
  57. package/dist/index.d.ts +9 -0
  58. package/dist/index.js +67 -0
  59. package/dist/lambda-context.d.ts +8 -0
  60. package/dist/lambda-context.js +33 -0
  61. package/dist/mailbox-row.d.ts +9 -0
  62. package/dist/mailbox-row.js +6 -0
  63. package/dist/poller.d.ts +1 -0
  64. package/dist/poller.js +51 -0
  65. package/dist/process.d.ts +6 -0
  66. package/dist/process.js +3 -0
  67. package/dist/processor.d.ts +3 -0
  68. package/dist/processor.js +44 -0
  69. package/dist/queues.d.ts +10 -0
  70. package/dist/queues.js +1 -0
  71. package/dist/s3-account-objects.d.ts +3 -0
  72. package/dist/s3-account-objects.js +26 -0
  73. package/dist/scheduler/attachment-sweep.d.ts +11 -0
  74. package/dist/scheduler/attachment-sweep.js +23 -0
  75. package/dist/scheduler/calendar-subscriptions.d.ts +26 -0
  76. package/dist/scheduler/calendar-subscriptions.js +35 -0
  77. package/dist/scheduler/config.d.ts +27 -0
  78. package/{src/scheduler/config.ts → dist/scheduler/config.js} +7 -26
  79. package/{src/scheduler/decide-due.ts → dist/scheduler/decide-due.d.ts} +3 -12
  80. package/dist/scheduler/decide-due.js +17 -0
  81. package/dist/scheduler/handler.d.ts +21 -0
  82. package/{src/scheduler/handler.ts → dist/scheduler/handler.js} +25 -42
  83. package/{src/scheduler/loop.ts → dist/scheduler/loop.d.ts} +7 -23
  84. package/dist/scheduler/loop.js +8 -0
  85. package/dist/scheduler/run-tick.d.ts +62 -0
  86. package/dist/scheduler/run-tick.js +164 -0
  87. package/dist/scheduler/runner.d.ts +2 -0
  88. package/{src/scheduler/runner.ts → dist/scheduler/runner.js} +57 -78
  89. package/dist/scheduler/stranded-placement-redrive.d.ts +16 -0
  90. package/dist/scheduler/stranded-placement-redrive.js +172 -0
  91. package/dist/sqs-queues.d.ts +4 -0
  92. package/dist/sqs-queues.js +22 -0
  93. package/dist/with-oauth-lifecycle-deps.d.ts +5 -0
  94. package/dist/with-oauth-lifecycle-deps.js +17 -0
  95. package/dist/with-oauth-lifecycle.d.ts +56 -0
  96. package/dist/with-oauth-lifecycle.js +92 -0
  97. package/{src/worker-version.ts → dist/worker-version.d.ts} +1 -2
  98. package/dist/worker-version.js +12 -0
  99. package/package.json +75 -69
  100. package/src/account-check.test.ts +0 -149
  101. package/src/account-check.ts +0 -101
  102. package/src/body-sync-gate.test.ts +0 -185
  103. package/src/body-sync-gate.ts +0 -86
  104. package/src/cli.ts +0 -218
  105. package/src/connection-scope.test.ts +0 -266
  106. package/src/connection-scope.ts +0 -314
  107. package/src/credential-less-sync-fence.test.ts +0 -152
  108. package/src/e2e-processor-shim.ts +0 -232
  109. package/src/emit.test.ts +0 -145
  110. package/src/emit.ts +0 -115
  111. package/src/events.ts +0 -252
  112. package/src/failure-kind.test.ts +0 -42
  113. package/src/handlers/append-sent-message.sqlite.test.ts +0 -176
  114. package/src/handlers/append-sent-message.ts +0 -264
  115. package/src/handlers/delete-account-objects.test.ts +0 -126
  116. package/src/handlers/delete-account-objects.ts +0 -96
  117. package/src/handlers/empty-trash.sqlite.test.ts +0 -209
  118. package/src/handlers/empty-trash.ts +0 -352
  119. package/src/handlers/flag-push.ts +0 -285
  120. package/src/handlers/imported-folder.test.ts +0 -63
  121. package/src/handlers/imported-folder.ts +0 -38
  122. package/src/handlers/mailbox-management.sqlite.test.ts +0 -265
  123. package/src/handlers/mailbox-management.ts +0 -486
  124. package/src/handlers/mailbox-sync-order.test.ts +0 -93
  125. package/src/handlers/mailbox-sync-order.ts +0 -65
  126. package/src/handlers/message-copy.sqlite.test.ts +0 -298
  127. package/src/handlers/message-copy.ts +0 -569
  128. package/src/handlers/message-delete-terminal.ts +0 -147
  129. package/src/handlers/message-delete.sqlite.test.ts +0 -291
  130. package/src/handlers/message-delete.ts +0 -888
  131. package/src/handlers/message-move.sqlite.test.ts +0 -271
  132. package/src/handlers/message-move.test.ts +0 -216
  133. package/src/handlers/message-move.ts +0 -755
  134. package/src/handlers/placement-move-push.test.ts +0 -137
  135. package/src/handlers/placement-move-push.ts +0 -478
  136. package/src/handlers/placement-push.sqlite.test.ts +0 -299
  137. package/src/handlers/probe-message-id.sqlite.test.ts +0 -192
  138. package/src/handlers/probe-message-id.ts +0 -15
  139. package/src/handlers/sync-mailboxes.test.ts +0 -183
  140. package/src/handlers/sync-mailboxes.ts +0 -425
  141. package/src/handlers/sync-message-body.sqlite.test.ts +0 -314
  142. package/src/handlers/sync-message-body.test.ts +0 -150
  143. package/src/handlers/sync-message-body.ts +0 -366
  144. package/src/handlers/sync-messages.sqlite.test.ts +0 -195
  145. package/src/handlers/sync-messages.ts +0 -537
  146. package/src/index.test.ts +0 -22
  147. package/src/index.ts +0 -82
  148. package/src/mail-sync-selection.sqlite.test.ts +0 -227
  149. package/src/mailbox-row.ts +0 -20
  150. package/src/pending-sync.sqlite.test.ts +0 -165
  151. package/src/poller.ts +0 -55
  152. package/src/processor.ts +0 -62
  153. package/src/queues.ts +0 -40
  154. package/src/scheduler/attachment-sweep.sqlite.test.ts +0 -74
  155. package/src/scheduler/attachment-sweep.ts +0 -46
  156. package/src/scheduler/calendar-subscriptions.sqlite.test.ts +0 -147
  157. package/src/scheduler/calendar-subscriptions.ts +0 -103
  158. package/src/scheduler/config.test.ts +0 -40
  159. package/src/scheduler/decide-due.test.ts +0 -44
  160. package/src/scheduler/half-deleted-accounts.sqlite.test.ts +0 -196
  161. package/src/scheduler/loop.test.ts +0 -143
  162. package/src/scheduler/run-tick.sqlite.test.ts +0 -191
  163. package/src/scheduler/run-tick.ts +0 -281
  164. package/src/scheduler/stranded-placement-redrive.ts +0 -265
  165. package/src/stranded-placement.sqlite.test.ts +0 -799
  166. package/src/test-helpers/test-world.ts +0 -425
  167. package/src/test-helpers/worker-queues.ts +0 -11
  168. package/src/thread-join.sqlite.test.ts +0 -106
  169. package/src/with-oauth-lifecycle-deps.sqlite.test.ts +0 -269
  170. package/src/with-oauth-lifecycle-deps.ts +0 -71
  171. package/src/with-oauth-lifecycle.ts +0 -158
  172. package/tsconfig.json +0 -8
@@ -1,265 +0,0 @@
1
- import type { RemitClient } from "@remit/backend/client";
2
- import type { AccountItem, MessageItem } from "@remit/data-ports";
3
- import { trashMailboxAt } from "@remit/data-ports/folder-role";
4
- import {
5
- deriveCopyMessageId,
6
- deriveMessageId,
7
- isValidMessageId,
8
- } from "@remit/data-ports/id";
9
- import { PATHLESS_MUTATION_EVENT_SCHEMA_VERSION } from "@remit/data-ports/mutation-events";
10
- import { MessageStatus, MessageSyncStatus } from "@remit/domain-enums";
11
- import type { Logger } from "@remit/logger";
12
- import { isCursorRebuildNeeded } from "@remit/mailbox-service";
13
- import type {
14
- MessageCopyEventV3,
15
- MessageDeleteEventV3,
16
- MessageMoveEventV3,
17
- PlacementMovePushEvent,
18
- } from "../events.js";
19
-
20
- /** Well past three attempts on a 60 s visibility timeout. */
21
- export const STRANDED_PLACEMENT_AFTER_MILLIS = 60 * 60 * 1000;
22
-
23
- type Unstamped<T> = Omit<T, "eventId" | "timestamp">;
24
-
25
- export type StrandedPlacementEvent =
26
- | Unstamped<PlacementMovePushEvent>
27
- | Unstamped<MessageDeleteEventV3>
28
- | Unstamped<MessageMoveEventV3>
29
- | Unstamped<MessageCopyEventV3>;
30
-
31
- export interface StrandedPlacementRedriveDeps {
32
- client: Pick<
33
- RemitClient,
34
- | "mailbox"
35
- | "mailboxSpecialUse"
36
- | "message"
37
- | "placementMove"
38
- | "threadMessage"
39
- >;
40
- emit: (event: StrandedPlacementEvent) => Promise<void>;
41
- log: Logger;
42
- }
43
-
44
- const isStrandedCopy = (row: MessageItem): boolean =>
45
- row.status === MessageStatus.moving &&
46
- row.uid === 0 &&
47
- typeof row.originalUid !== "number";
48
-
49
- type CopyRedrive =
50
- | { kind: "redrive"; event: Unstamped<MessageCopyEventV3> }
51
- | { kind: "unresolvable"; reason: string }
52
- | { kind: "wait" };
53
-
54
- /**
55
- * The message a uid-0 copy was made from: its id derives from the Message-ID
56
- * the copy's listing row carries, and the copy's own id derives from it.
57
- */
58
- const copyRedriveFor = async (
59
- client: StrandedPlacementRedriveDeps["client"],
60
- account: AccountItem,
61
- copy: MessageItem,
62
- ): Promise<CopyRedrive> => {
63
- const listing = await client.threadMessage.findByMessageId(
64
- account.accountConfigId,
65
- copy.messageId,
66
- );
67
- if (!listing) return { kind: "unresolvable", reason: "listing row missing" };
68
- const header = listing.messageIdHeader;
69
- if (!header || !isValidMessageId(header)) {
70
- return { kind: "unresolvable", reason: "listing row has no Message-ID" };
71
- }
72
- const sourceId = deriveMessageId(account.accountId, header);
73
- if (deriveCopyMessageId(sourceId, copy.mailboxId) !== copy.messageId) {
74
- return {
75
- kind: "unresolvable",
76
- reason: "copy was not made from the message its Message-ID names",
77
- };
78
- }
79
- const [source] = await client.message.get([sourceId]);
80
- if (!source) return { kind: "unresolvable", reason: "source row missing" };
81
- if (source.status === MessageStatus.deleted) {
82
- return { kind: "unresolvable", reason: "source row deleted" };
83
- }
84
- if (source.status !== MessageStatus.active) return { kind: "wait" };
85
- return {
86
- kind: "redrive",
87
- event: {
88
- type: "MESSAGE_COPY",
89
- schemaVersion: PATHLESS_MUTATION_EVENT_SCHEMA_VERSION,
90
- accountId: account.accountId,
91
- sourceMessageId: source.messageId,
92
- newMessageId: copy.messageId,
93
- sourceMailboxId: source.mailboxId,
94
- destinationMailboxId: copy.mailboxId,
95
- uid: source.uid,
96
- },
97
- };
98
- };
99
-
100
- /** A copy with no source to copy from has nothing to bind and nothing to hide. */
101
- const removeUnresolvableCopy = async (
102
- deps: StrandedPlacementRedriveDeps,
103
- account: AccountItem,
104
- row: MessageItem,
105
- reason: string,
106
- now: number,
107
- ): Promise<boolean> => {
108
- const removed = await deps.client.message.deleteIfPlacement(row.messageId, {
109
- status: MessageStatus.moving,
110
- mailboxId: row.mailboxId,
111
- uid: 0,
112
- });
113
- if (!removed) return false;
114
- deps.log.error(
115
- {
116
- alert: "stranded_copy_unresolvable",
117
- accountId: account.accountId,
118
- messageId: row.messageId,
119
- mailboxId: row.mailboxId,
120
- reason,
121
- untouchedForMs: now - row.updatedAt,
122
- },
123
- "A copy stranded at uid 0 has no source to copy from; the copy row was removed",
124
- );
125
- return true;
126
- };
127
-
128
- const eventFor = async (
129
- client: StrandedPlacementRedriveDeps["client"],
130
- account: AccountItem,
131
- row: MessageItem,
132
- trashMailboxId: string | undefined,
133
- ): Promise<StrandedPlacementEvent | undefined> => {
134
- const { accountId, accountConfigId } = account;
135
- const { messageId } = row;
136
-
137
- if (row.status === MessageStatus.deleting) {
138
- return {
139
- type: "MESSAGE_DELETE",
140
- schemaVersion: PATHLESS_MUTATION_EVENT_SCHEMA_VERSION,
141
- accountId,
142
- messageId,
143
- mailboxId: row.mailboxId,
144
- uid: row.uid,
145
- operation: "permanent_delete",
146
- };
147
- }
148
- if (
149
- typeof row.originalMailboxId !== "string" ||
150
- typeof row.originalUid !== "number"
151
- ) {
152
- return undefined;
153
- }
154
-
155
- const marker = await client.placementMove.find(messageId);
156
- if (marker && marker.destinationMailboxId === row.mailboxId) {
157
- return {
158
- type: "PLACEMENT_MOVE_PUSH",
159
- accountId,
160
- accountConfigId,
161
- messageId,
162
- };
163
- }
164
- if (row.mailboxId === trashMailboxId) {
165
- return {
166
- type: "MESSAGE_DELETE",
167
- schemaVersion: PATHLESS_MUTATION_EVENT_SCHEMA_VERSION,
168
- accountId,
169
- messageId,
170
- mailboxId: row.originalMailboxId,
171
- uid: row.originalUid,
172
- operation: "move_to_trash",
173
- destinationMailboxId: row.mailboxId,
174
- };
175
- }
176
- return {
177
- type: "MESSAGE_MOVE",
178
- schemaVersion: PATHLESS_MUTATION_EVENT_SCHEMA_VERSION,
179
- accountId,
180
- messageId,
181
- sourceMailboxId: row.originalMailboxId,
182
- destinationMailboxId: row.mailboxId,
183
- uid: row.originalUid,
184
- };
185
- };
186
-
187
- /** The claim restarts the row's clock; a folder awaiting a cursor rebuild waits until it is normal. */
188
- export const redriveStrandedPlacements = async (
189
- deps: StrandedPlacementRedriveDeps,
190
- account: AccountItem,
191
- now: number,
192
- ): Promise<number> => {
193
- const { client, emit, log } = deps;
194
- const { accountId } = account;
195
-
196
- const mailboxes = await client.mailbox.listAllByAccount(accountId);
197
- const paused = new Set(
198
- mailboxes
199
- .filter((mailbox) => isCursorRebuildNeeded(mailbox.cursorState))
200
- .map((mailbox) => mailbox.mailboxId),
201
- );
202
- const stranded = (
203
- await client.message.listStrandedPlacements(
204
- mailboxes.map((mailbox) => mailbox.mailboxId),
205
- now - STRANDED_PLACEMENT_AFTER_MILLIS,
206
- )
207
- ).filter(
208
- (row) =>
209
- !paused.has(row.mailboxId) &&
210
- !(row.originalMailboxId && paused.has(row.originalMailboxId)),
211
- );
212
- if (stranded.length === 0) return 0;
213
-
214
- const trash = trashMailboxAt(
215
- await client.mailboxSpecialUse.resolveTrashRole(accountId),
216
- "resolved",
217
- );
218
- const trashMailboxId = trash.allowed ? trash.mailbox.mailboxId : undefined;
219
-
220
- let redriven = 0;
221
- for (const row of stranded) {
222
- const copy = isStrandedCopy(row)
223
- ? await copyRedriveFor(client, account, row)
224
- : undefined;
225
- if (copy?.kind === "wait") continue;
226
- if (copy?.kind === "unresolvable") {
227
- if (await removeUnresolvableCopy(deps, account, row, copy.reason, now)) {
228
- redriven += 1;
229
- }
230
- continue;
231
- }
232
- const event =
233
- copy?.kind === "redrive"
234
- ? copy.event
235
- : await eventFor(client, account, row, trashMailboxId);
236
- if (!event) continue;
237
-
238
- // A copy's earlier COPY may have landed with its answer lost, so the
239
- // re-drive marks it `failed`: the copy handler then asks the destination
240
- // before it copies again.
241
- const claimed = await client.message.transitionPlacement(
242
- row.messageId,
243
- { status: row.status, mailboxId: row.mailboxId, uid: row.uid },
244
- {
245
- syncStatus: copy ? MessageSyncStatus.failed : MessageSyncStatus.pending,
246
- },
247
- );
248
- if (!claimed) continue;
249
-
250
- await emit(event);
251
- redriven += 1;
252
- log.warn(
253
- {
254
- metric: "stranded_placement_redriven",
255
- accountId,
256
- messageId: row.messageId,
257
- event: event.type,
258
- syncStatus: row.syncStatus,
259
- untouchedForMs: now - row.updatedAt,
260
- },
261
- "A move or delete had no event left to settle it; re-driven",
262
- );
263
- }
264
- return redriven;
265
- };