@remit/account-worker 0.0.25 → 0.0.27

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/account-worker",
3
- "version": "0.0.25",
3
+ "version": "0.0.27",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -33,6 +33,7 @@
33
33
  "dev": "node --import tsx src/poller.ts"
34
34
  },
35
35
  "dependencies": {
36
+ "@remit/logger": "*",
36
37
  "@remit/data-ports": "*",
37
38
  "@remit/logger-lambda": "*",
38
39
  "@remit/drizzle-service": "*",
@@ -40,7 +41,6 @@
40
41
  "@remit/sqs-client": "*",
41
42
  "@remit/storage-service": "*",
42
43
  "@remit/electrodb-entities": "*",
43
- "@remit/search-index-worker": "*",
44
44
  "@aws-sdk/client-sqs": "*",
45
45
  "archiver": "*",
46
46
  "electrodb": "*",
@@ -1,7 +1,7 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { describe, it } from "node:test";
3
3
  import type { MessageDescription } from "@remit/data-ports";
4
- import { noopLogger } from "@remit/logger-lambda/noop-logger";
4
+ import { noopLogger } from "@remit/logger";
5
5
  import {
6
6
  type CascadeEntity,
7
7
  type CascadeServices,
@@ -18,11 +18,10 @@ const messageWithChildren = {
18
18
  bodyPartParameter: [{ bodyPartParameterId: "bpp-1" }],
19
19
  rawMessageStorage: [{ rawStorageId: "rms-1" }],
20
20
  bodyPartStorage: [{ bodyPartStorageId: "bps-1" }],
21
- bodyPartContent: [{ bodyPartContentId: "bpc-1" }],
22
21
  } as unknown as MessageDescription;
23
22
 
24
23
  describe("collectMessageChildEntities", () => {
25
- it("expands the nine child entities of one message", () => {
24
+ it("expands the eight child entities of one message", () => {
26
25
  const entities: CascadeEntity[] = [];
27
26
  collectMessageChildEntities(entities, messageWithChildren);
28
27
 
@@ -36,13 +35,7 @@ describe("collectMessageChildEntities", () => {
36
35
  "BodyPartParameter",
37
36
  "RawMessageStorage",
38
37
  "BodyPartStorage",
39
- "BodyPartContent",
40
38
  ]);
41
- assert.equal(
42
- entities.find((e) => e.entityType === "BodyPartContent")?.key
43
- .bodyPartContentId,
44
- "bpc-1",
45
- );
46
39
  });
47
40
 
48
41
  it("appends nothing when every child list is empty", () => {
@@ -56,7 +49,6 @@ describe("collectMessageChildEntities", () => {
56
49
  bodyPartParameter: [],
57
50
  rawMessageStorage: [],
58
51
  bodyPartStorage: [],
59
- bodyPartContent: [],
60
52
  } as unknown as MessageDescription);
61
53
  assert.equal(entities.length, 0);
62
54
  });
@@ -96,13 +88,7 @@ const fullServices = (): CascadeServices =>
96
88
  listByAccountConfig: async () => [{ accountSettingId: "set-1" }],
97
89
  },
98
90
  filterService: {
99
- listByAccountConfig: async () => [
100
- { filterId: "flt-1", hasAnchor: true },
101
- { filterId: "flt-2", hasAnchor: false },
102
- ],
103
- },
104
- filterAnchorService: {
105
- get: async () => ({ filterId: "flt-1" }),
91
+ listByAccountConfig: async () => [{ filterId: "flt-1" }],
106
92
  },
107
93
  labelService: {
108
94
  listByAccountConfig: async () => [{ labelId: "lbl-1" }],
@@ -128,7 +114,6 @@ describe("enumerateCascadeEntities", () => {
128
114
  "Mailbox",
129
115
  "Message",
130
116
  "MessageFlag",
131
- "BodyPartContent",
132
117
  "OutboxMessage",
133
118
  "MailboxLock",
134
119
  "MessagePlacementMove",
@@ -136,7 +121,6 @@ describe("enumerateCascadeEntities", () => {
136
121
  "ThreadMessage",
137
122
  "AccountSetting",
138
123
  "Filter",
139
- "FilterAnchor",
140
124
  "Label",
141
125
  "MessageLabel",
142
126
  "Address",
@@ -148,40 +132,6 @@ describe("enumerateCascadeEntities", () => {
148
132
  assert.equal(types[types.length - 1], "AccountConfig");
149
133
  });
150
134
 
151
- it("emits a Filter without a FilterAnchor when the filter has no anchor", async () => {
152
- const services = fullServices();
153
- services.filterService.listByAccountConfig = async () =>
154
- [{ filterId: "flt-2", hasAnchor: false }] as never;
155
-
156
- const { entities } = await enumerateCascadeEntities(
157
- "cfg-1",
158
- services,
159
- noopLogger,
160
- );
161
-
162
- assert.equal(entities.filter((e) => e.entityType === "Filter").length, 1);
163
- assert.equal(
164
- entities.filter((e) => e.entityType === "FilterAnchor").length,
165
- 0,
166
- );
167
- });
168
-
169
- it("skips the FilterAnchor when the anchor lookup returns null", async () => {
170
- const services = fullServices();
171
- services.filterAnchorService.get = async () => null as never;
172
-
173
- const { entities } = await enumerateCascadeEntities(
174
- "cfg-1",
175
- services,
176
- noopLogger,
177
- );
178
-
179
- assert.equal(
180
- entities.filter((e) => e.entityType === "FilterAnchor").length,
181
- 0,
182
- );
183
- });
184
-
185
135
  it("yields only the AccountConfig row for an empty tenant", async () => {
186
136
  const services = fullServices();
187
137
  services.accountConfigService.describe = async () =>
package/src/cascade.ts CHANGED
@@ -5,7 +5,6 @@ import type {
5
5
  IAccountSettingRepository,
6
6
  IAddressRepository,
7
7
  IEnvelopeRepository,
8
- IFilterAnchorRepository,
9
8
  IFilterRepository,
10
9
  ILabelRepository,
11
10
  IMailboxLockRepository,
@@ -19,7 +18,7 @@ import type {
19
18
  IThreadMessageRepository,
20
19
  MessageDescription,
21
20
  } from "@remit/data-ports";
22
- import type { Logger } from "@remit/logger-lambda";
21
+ import type { Logger } from "@remit/logger";
23
22
 
24
23
  export interface CascadeEntity {
25
24
  entityType: string;
@@ -42,7 +41,6 @@ export interface CascadeServices {
42
41
  accountExportRequestService: IAccountExportRequestRepository;
43
42
  accountSettingService: IAccountSettingRepository;
44
43
  filterService: IFilterRepository;
45
- filterAnchorService: IFilterAnchorRepository;
46
44
  labelService: ILabelRepository;
47
45
  messageLabelService: IMessageLabelRepository;
48
46
  }
@@ -111,12 +109,6 @@ export const collectMessageChildEntities = (
111
109
  key: { bodyPartStorageId: bps.bodyPartStorageId },
112
110
  });
113
111
  }
114
- for (const bpc of messageData.bodyPartContent) {
115
- entities.push({
116
- entityType: "BodyPartContent",
117
- key: { bodyPartContentId: bpc.bodyPartContentId },
118
- });
119
- }
120
112
  };
121
113
 
122
114
  export const enumerateCascadeEntities = async (
@@ -138,7 +130,6 @@ export const enumerateCascadeEntities = async (
138
130
  messageFlagPushService,
139
131
  accountSettingService,
140
132
  filterService,
141
- filterAnchorService,
142
133
  labelService,
143
134
  messageLabelService,
144
135
  } = services;
@@ -225,13 +216,6 @@ export const enumerateCascadeEntities = async (
225
216
  key: { bodyPartStorageId: bps.bodyPartStorageId },
226
217
  });
227
218
  }
228
-
229
- for (const bpc of messageData.bodyPartContent) {
230
- entities.push({
231
- entityType: "BodyPartContent",
232
- key: { bodyPartContentId: bpc.bodyPartContentId },
233
- });
234
- }
235
219
  }
236
220
  }
237
221
 
@@ -292,7 +276,7 @@ export const enumerateCascadeEntities = async (
292
276
  });
293
277
  }
294
278
 
295
- // Filter/FilterAnchor/Label/MessageLabel are accountConfig-scoped (RFC 034),
279
+ // Filter/Label/MessageLabel are accountConfig-scoped (RFC 034),
296
280
  // not per sub-account, so — like AccountSetting and ThreadMessage above —
297
281
  // they are enumerated once here rather than inside the per-account loop.
298
282
  const filters = await filterService.listByAccountConfig(accountConfigId);
@@ -301,16 +285,6 @@ export const enumerateCascadeEntities = async (
301
285
  entityType: "Filter",
302
286
  key: { accountConfigId, filterId: filter.filterId },
303
287
  });
304
- if (!filter.hasAnchor) continue;
305
- const anchor = await filterAnchorService.get(
306
- accountConfigId,
307
- filter.filterId,
308
- );
309
- if (!anchor) continue;
310
- entities.push({
311
- entityType: "FilterAnchor",
312
- key: { accountConfigId, filterId: filter.filterId },
313
- });
314
288
  }
315
289
 
316
290
  const labels = await labelService.listByAccountConfig(accountConfigId);
@@ -354,30 +328,3 @@ export const enumerateCascadeEntities = async (
354
328
 
355
329
  return { entities, messageIds };
356
330
  };
357
-
358
- export const COVERED_ENTITY_TYPES = [
359
- "Account",
360
- "AccountConfig",
361
- "AccountSetting",
362
- "Address",
363
- "BodyPart",
364
- "BodyPartContent",
365
- "BodyPartParameter",
366
- "BodyPartStorage",
367
- "Envelope",
368
- "EnvelopeAddress",
369
- "Filter",
370
- "FilterAnchor",
371
- "Label",
372
- "Mailbox",
373
- "MailboxLock",
374
- "Message",
375
- "MessageFlag",
376
- "MessageFlagPush",
377
- "MessageLabel",
378
- "MessagePlacementMove",
379
- "MessageReference",
380
- "OutboxMessage",
381
- "RawMessageStorage",
382
- "ThreadMessage",
383
- ] as const;
@@ -3,7 +3,7 @@ import { mkdir, mkdtemp, stat, writeFile } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { dirname, join } from "node:path";
5
5
  import { afterEach, beforeEach, describe, it } from "node:test";
6
- import { noopLogger } from "@remit/logger-lambda/noop-logger";
6
+ import { noopLogger } from "@remit/logger";
7
7
  import { buildRelationalDeletionCapabilities } from "./compose-relational.js";
8
8
 
9
9
  const exists = (path: string): Promise<boolean> =>
@@ -79,16 +79,3 @@ describe("relational deletion capabilities — filesystem storage cleanup", () =
79
79
  await caps.deleteStoragePrefix("accounts/never-existed/", noopLogger);
80
80
  });
81
81
  });
82
-
83
- describe("relational deletion capabilities — CDN and sign-out are no-ops", () => {
84
- it("invalidateContent resolves without a CDN", async () => {
85
- const caps = buildRelationalDeletionCapabilities();
86
- await caps.invalidateContent("cfg-1", noopLogger);
87
- await caps.invalidateContent("cfg-1/acc-1", noopLogger);
88
- });
89
-
90
- it("signOut resolves without a federated session store", async () => {
91
- const caps = buildRelationalDeletionCapabilities();
92
- await caps.signOut("user-123", noopLogger);
93
- });
94
- });
@@ -3,9 +3,9 @@ import { join } from "node:path";
3
3
  import {
4
4
  type CascadeDeleter,
5
5
  createSqliteCascadeDeleter,
6
+ sqliteDatabasePathsFromEnv,
6
7
  } from "@remit/drizzle-service";
7
- import type { Logger } from "@remit/logger-lambda";
8
- import { env } from "expect-env";
8
+ import type { Logger } from "@remit/logger";
9
9
  import type { DeletionCapabilities } from "./deletion-capabilities.js";
10
10
 
11
11
  // Mirrors `@remit/storage-service`'s filesystem-backend default: bodies
@@ -30,14 +30,14 @@ const deleteStoragePrefix = async (
30
30
  };
31
31
 
32
32
  // The Drizzle cascade deleter is opened once, on first use, and reused: it
33
- // opens the shared file at `SQLITE_DB_PATH` (the native binding loads there,
33
+ // opens the app, mail and search databases (the native binding loads there,
34
34
  // hence async). Built lazily so the fanout worker — which signs out but never
35
35
  // cascade-deletes — does not open a database handle it will not use.
36
36
  let deleterPromise: Promise<CascadeDeleter> | undefined;
37
37
 
38
38
  const getDeleter = (): Promise<CascadeDeleter> => {
39
39
  if (!deleterPromise)
40
- deleterPromise = createSqliteCascadeDeleter(env.SQLITE_DB_PATH);
40
+ deleterPromise = createSqliteCascadeDeleter(sqliteDatabasePathsFromEnv());
41
41
  return deleterPromise;
42
42
  };
43
43
 
@@ -52,8 +52,7 @@ const getDeleter = (): Promise<CascadeDeleter> => {
52
52
  * backend with no response cache (`deploy/vps/caddy/routes.caddy`), so there
53
53
  * is nothing to invalidate.
54
54
  * - `deleteStoragePrefix`: recursive filesystem removal.
55
- * - `cascadeDelete`: the Drizzle cascade over SQLite. Message
56
- * subtrees emit `message.removed` outbox rows the search-index worker relays.
55
+ * - `cascadeDelete`: the Drizzle cascade over SQLite.
57
56
  */
58
57
  export const buildRelationalDeletionCapabilities =
59
58
  (): DeletionCapabilities => ({
@@ -51,9 +51,4 @@ describe("getImapWorkerQueueUrl", () => {
51
51
  delete process.env.SQS_QUEUE_URL_IMAP_WORKER;
52
52
  assert.equal(getImapWorkerQueueUrl(), undefined);
53
53
  });
54
-
55
- it("returns the configured value when set", () => {
56
- process.env.SQS_QUEUE_URL_IMAP_WORKER = "http://queue/imap-worker";
57
- assert.equal(getImapWorkerQueueUrl(), "http://queue/imap-worker");
58
- });
59
54
  });
package/src/config.ts CHANGED
@@ -26,8 +26,6 @@ export const getSqsClient = (queueUrl: string): SQSClient => {
26
26
  // no queue, so its Lambda doesn't carry the env vars. Eager evaluation here would
27
27
  // crash finalize at module load — getters defer the read to the fanout-only call
28
28
  // sites.
29
- export const getSearchIndexQueueUrl = (): string =>
30
- env.SQS_QUEUE_URL_SEARCH_INDEX;
31
29
  // Optional, and read through `process.env` rather than expect-env so an unset
32
30
  // var yields undefined instead of throwing. IMAP_WORKER_STOP is a no-op
33
31
  // acknowledgement in the cascade contract — the account tombstone fence is what
@@ -48,7 +46,7 @@ let cascadeServicesPromise: Promise<CascadeServices> | null = null;
48
46
 
49
47
  // Every cascade service is a `RemitClient` repository, so the whole enumeration
50
48
  // runs on whatever backend `getClient()` resolved — DynamoDB (ElectroDB) or
51
- // SQLite (Drizzle). Filter/FilterAnchor/Label/MessageLabel (Smart Organize,
49
+ // SQLite (Drizzle). Filter/Label/MessageLabel (Smart Organize,
52
50
  // RFC 034) are present on both via the client, so they need no
53
51
  // backend-specific wiring here.
54
52
  export const getCascadeServices = (): Promise<CascadeServices> => {
@@ -69,7 +67,6 @@ export const getCascadeServices = (): Promise<CascadeServices> => {
69
67
  accountExportRequestService: remitClient.accountExportRequest,
70
68
  accountSettingService: remitClient.accountSetting,
71
69
  filterService: remitClient.filter,
72
- filterAnchorService: remitClient.filterAnchor,
73
70
  labelService: remitClient.label,
74
71
  messageLabelService: remitClient.messageLabel,
75
72
  }));
@@ -84,5 +81,3 @@ export const getStorageService = (): StorageService => {
84
81
  }
85
82
  return storageService;
86
83
  };
87
-
88
- export const dataBackend = process.env.DATA_BACKEND;
@@ -1,4 +1,4 @@
1
- import type { Logger } from "@remit/logger-lambda";
1
+ import type { Logger } from "@remit/logger";
2
2
  import type { CascadeEntity } from "./cascade.js";
3
3
 
4
4
  /**
@@ -71,7 +71,7 @@ export const setDeletionCapabilities = (
71
71
  const buildDeletionCapabilitiesFromEnv =
72
72
  async (): Promise<DeletionCapabilities> => {
73
73
  if (injectedCapabilities) return injectedCapabilities;
74
- if (process.env.SQLITE_DB_PATH) {
74
+ if (process.env.SQLITE_APP_DB_PATH) {
75
75
  const { buildRelationalDeletionCapabilities } = await import(
76
76
  "./compose-relational.js"
77
77
  );
package/src/events.ts CHANGED
@@ -9,7 +9,7 @@ export type AccountDeleteEvent = {
9
9
 
10
10
  /**
11
11
  * Per-account hard-delete. Purges ONE mail account's data (mailboxes,
12
- * messages, body parts, thread messages, S3 objects, search vectors) while
12
+ * messages, body parts, thread messages, S3 objects) while
13
13
  * keeping the AccountConfig/tenant and any sibling accounts intact. Emitted
14
14
  * by the API on `deleteAccount`; consumed by the fanout worker.
15
15
  */
@@ -1,7 +1,7 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { Readable } from "node:stream";
3
3
  import { describe, it } from "node:test";
4
- import { noopLogger } from "@remit/logger-lambda/noop-logger";
4
+ import { noopLogger } from "@remit/logger";
5
5
  import type { StorageService } from "@remit/storage-service";
6
6
  import type { CascadeServices } from "../cascade.js";
7
7
  import type { AccountExportEvent } from "../events.js";
@@ -1,5 +1,5 @@
1
1
  import { PassThrough } from "node:stream";
2
- import type { Logger } from "@remit/logger-lambda";
2
+ import type { Logger } from "@remit/logger";
3
3
  import type { StorageService } from "@remit/storage-service";
4
4
  import { ZipArchive } from "archiver";
5
5
  import type { CascadeServices } from "../cascade.js";
@@ -1,7 +1,7 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { afterEach, describe, it } from "node:test";
3
3
  import type { SQSClient } from "@aws-sdk/client-sqs";
4
- import { noopLogger } from "@remit/logger-lambda/noop-logger";
4
+ import { noopLogger } from "@remit/logger";
5
5
  import type { CascadeServices } from "../cascade.js";
6
6
  import type { AccountDeleteEvent } from "../events.js";
7
7
  import { processAccountFanout } from "./account-fanout.js";
@@ -32,7 +32,6 @@ const buildServices = (): CascadeServices =>
32
32
  threadMessageService: { listAllByAccount: async () => [] },
33
33
  accountSettingService: { listByAccountConfig: async () => [] },
34
34
  filterService: { listByAccountConfig: async () => [] },
35
- filterAnchorService: { get: async () => null },
36
35
  labelService: { listByAccountConfig: async () => [] },
37
36
  messageLabelService: { listByLabelId: async () => [] },
38
37
  }) as unknown as CascadeServices;
@@ -1,11 +1,10 @@
1
1
  import { SendMessageCommand, type SQSClient } from "@aws-sdk/client-sqs";
2
+ import { createLogger, type Logger } from "@remit/logger";
2
3
  import {
3
- createLogger,
4
- type Logger,
5
4
  queueNameFromEventSource,
6
5
  recordQueueEvent,
7
- withTelemetry,
8
- } from "@remit/logger-lambda";
6
+ } from "@remit/logger-lambda/metrics";
7
+ import { installNodeLogger, withTelemetry } from "@remit/logger-lambda/node";
9
8
  import type { SQSBatchResponse, SQSEvent, SQSHandler } from "aws-lambda";
10
9
  import type { CascadeServices } from "../cascade.js";
11
10
  import { enumerateCascadeEntities } from "../cascade.js";
@@ -30,6 +29,8 @@ import { processAccountDataPurge } from "./account-purge.js";
30
29
  import { processOrganizeJob } from "./organize-job.js";
31
30
  import { processSenderCategoryBackApply } from "./sender-category-backapply.js";
32
31
 
32
+ installNodeLogger();
33
+
33
34
  export interface ProcessAccountFanoutDeps {
34
35
  services?: CascadeServices;
35
36
  sqs?: SQSClient;
@@ -41,8 +42,8 @@ export interface ProcessAccountFanoutDeps {
41
42
 
42
43
  /**
43
44
  * Fanout step of the account-deletion cascade. Read-only: enumerates the
44
- * AccountConfig's data and dispatches downstream work — search-index
45
- * deletes, per-account imap-worker stops, a sign-out, and the finalize
45
+ * AccountConfig's data and dispatches downstream work — per-account
46
+ * imap-worker stops, a sign-out, and the finalize
46
47
  * enqueue. Throws on any non-swallowable error so SQS partial batch-failure
47
48
  * retries the whole record.
48
49
  */
@@ -1,11 +1,10 @@
1
1
  import { inspect } from "node:util";
2
+ import { createLogger, type Logger } from "@remit/logger";
2
3
  import {
3
- createLogger,
4
- type Logger,
5
4
  queueNameFromEventSource,
6
5
  recordQueueEvent,
7
- withTelemetry,
8
- } from "@remit/logger-lambda";
6
+ } from "@remit/logger-lambda/metrics";
7
+ import { installNodeLogger, withTelemetry } from "@remit/logger-lambda/node";
9
8
  import type { SQSEvent, SQSHandler } from "aws-lambda";
10
9
  import {
11
10
  type CascadeEntity,
@@ -24,6 +23,8 @@ import type {
24
23
  AccountFinalizeEvent,
25
24
  } from "../events.js";
26
25
 
26
+ installNodeLogger();
27
+
27
28
  export interface ProcessFinalizeDeps {
28
29
  capabilities?: DeletionCapabilities;
29
30
  cascadeServices?: CascadeServices;
@@ -131,10 +132,7 @@ export const processAccountFinalize = async (
131
132
  * the work; this worker only ever consumes.
132
133
  *
133
134
  * Idempotency: the cascade on a missing key is a no-op, so a redelivered batch
134
- * (or container) no-ops on already-gone rows. Search-index cleanup is not driven
135
- * from here: on DynamoDB the fanout step enqueues a REMOVE per message id up
136
- * front; on the relational backends the cascade emits a `message.removed` outbox
137
- * row the search-index worker relays.
135
+ * (or container) no-ops on already-gone rows.
138
136
  */
139
137
  export const processAccountDataPurgeFinalize = async (
140
138
  event: AccountDataPurgeFinalizeEvent,
@@ -1,7 +1,7 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { describe, it } from "node:test";
3
3
  import type { SQSClient } from "@aws-sdk/client-sqs";
4
- import { noopLogger } from "@remit/logger-lambda/noop-logger";
4
+ import { noopLogger } from "@remit/logger";
5
5
  import type { CascadeServices } from "../cascade.js";
6
6
  import type { AccountDataPurgeEvent } from "../events.js";
7
7
  import {
@@ -12,28 +12,19 @@ import {
12
12
  interface Sent {
13
13
  queueUrl: string | undefined;
14
14
  body: Record<string, unknown>;
15
- entries?: Array<{ Id: string; MessageBody: string }>;
16
15
  }
17
16
 
18
- const recordingSqs = (sent: Sent[], failBatch = false): SQSClient =>
17
+ const recordingSqs = (sent: Sent[]): SQSClient =>
19
18
  ({
20
19
  send: async (command: {
21
- input: {
22
- QueueUrl?: string;
23
- MessageBody?: string;
24
- Entries?: Array<{ Id: string; MessageBody: string }>;
25
- };
20
+ input: { QueueUrl?: string; MessageBody?: string };
26
21
  }) => {
27
22
  sent.push({
28
23
  queueUrl: command.input.QueueUrl,
29
24
  body: command.input.MessageBody
30
25
  ? JSON.parse(command.input.MessageBody)
31
26
  : {},
32
- entries: command.input.Entries,
33
27
  });
34
- if (command.input.Entries && failBatch) {
35
- return { Failed: [{ Id: "0" }] };
36
- }
37
28
  return {};
38
29
  },
39
30
  }) as unknown as SQSClient;
@@ -73,19 +64,14 @@ const baseDeps = (
73
64
  ]),
74
65
  sqs: recordingSqs(sent),
75
66
  accountPurgeDeleteQueueUrl: "http://queue/purge",
76
- searchIndexQueueUrl: "http://queue/search",
77
- dataBackend: "dynamodb",
78
67
  ...overrides,
79
68
  });
80
69
 
81
70
  describe("processAccountDataPurge", () => {
82
- it("enqueues vector deletes then a subtrees batch and one container leftover", async () => {
71
+ it("enqueues a subtrees batch and one container leftover", async () => {
83
72
  const sent: Sent[] = [];
84
73
  await processAccountDataPurge(event, noopLogger, baseDeps(sent));
85
74
 
86
- const vectorBatch = sent.find((m) => m.queueUrl === "http://queue/search");
87
- assert.equal(vectorBatch?.entries?.length, 2, "one entry per message");
88
-
89
75
  const finalize = sent.filter((m) => m.queueUrl === "http://queue/purge");
90
76
  const kinds = finalize.map((m) => m.body.kind);
91
77
  assert.deepEqual(kinds, ["subtrees", "container"]);
@@ -96,27 +82,6 @@ describe("processAccountDataPurge", () => {
96
82
  );
97
83
  });
98
84
 
99
- it("skips vector deletes on the relational backend, still enqueuing finalize", async () => {
100
- const sent: Sent[] = [];
101
- await processAccountDataPurge(
102
- event,
103
- noopLogger,
104
- baseDeps(sent, { dataBackend: "sqlite" }),
105
- );
106
-
107
- assert.equal(
108
- sent.some((m) => m.queueUrl === "http://queue/search"),
109
- false,
110
- "no search-index enqueue on the relational backend",
111
- );
112
- assert.deepEqual(
113
- sent
114
- .filter((m) => m.queueUrl === "http://queue/purge")
115
- .map((m) => m.body.kind),
116
- ["subtrees", "container"],
117
- );
118
- });
119
-
120
85
  it("drops manifest rows outside the account's mailbox set", async () => {
121
86
  const sent: Sent[] = [];
122
87
  await processAccountDataPurge(event, noopLogger, {
@@ -167,15 +132,4 @@ describe("processAccountDataPurge", () => {
167
132
  /dynamo throttled/,
168
133
  );
169
134
  });
170
-
171
- it("throws when a vector-delete batch reports failed entries", async () => {
172
- const sent: Sent[] = [];
173
- await assert.rejects(
174
- processAccountDataPurge(event, noopLogger, {
175
- ...baseDeps(sent),
176
- sqs: recordingSqs(sent, true),
177
- }),
178
- /failed entries/,
179
- );
180
- });
181
135
  });