@serve.zone/coremail 1.0.0
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/.smartconfig.json +50 -0
- package/changelog.md +10 -0
- package/cli.js +4 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.auth.d.ts +45 -0
- package/dist_ts/classes.auth.js +204 -0
- package/dist_ts/classes.config.d.ts +2 -0
- package/dist_ts/classes.config.js +72 -0
- package/dist_ts/classes.coremail.d.ts +41 -0
- package/dist_ts/classes.coremail.js +155 -0
- package/dist_ts/classes.desiredstate.d.ts +40 -0
- package/dist_ts/classes.desiredstate.js +382 -0
- package/dist_ts/classes.gateway.d.ts +62 -0
- package/dist_ts/classes.gateway.js +669 -0
- package/dist_ts/classes.inbound.d.ts +49 -0
- package/dist_ts/classes.inbound.js +702 -0
- package/dist_ts/classes.maintenance.d.ts +16 -0
- package/dist_ts/classes.maintenance.js +339 -0
- package/dist_ts/classes.models.d.ts +161 -0
- package/dist_ts/classes.models.js +595 -0
- package/dist_ts/classes.server.d.ts +40 -0
- package/dist_ts/classes.server.js +309 -0
- package/dist_ts/classes.storage.d.ts +32 -0
- package/dist_ts/classes.storage.js +317 -0
- package/dist_ts/classes.submissions.d.ts +33 -0
- package/dist_ts/classes.submissions.js +385 -0
- package/dist_ts/classes.transfer.d.ts +41 -0
- package/dist_ts/classes.transfer.js +289 -0
- package/dist_ts/coremail.cursor.d.ts +20 -0
- package/dist_ts/coremail.cursor.js +191 -0
- package/dist_ts/coremail.log.d.ts +3 -0
- package/dist_ts/coremail.log.js +11 -0
- package/dist_ts/coremail.mime.d.ts +8 -0
- package/dist_ts/coremail.mime.js +63 -0
- package/dist_ts/coremail.persistence.d.ts +148 -0
- package/dist_ts/coremail.persistence.js +695 -0
- package/dist_ts/coremail.quota.d.ts +29 -0
- package/dist_ts/coremail.quota.js +149 -0
- package/dist_ts/coremail.selectors.d.ts +3 -0
- package/dist_ts/coremail.selectors.js +21 -0
- package/dist_ts/coremail.validation.d.ts +9 -0
- package/dist_ts/coremail.validation.js +325 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +39 -0
- package/dist_ts/interfaces.d.ts +92 -0
- package/dist_ts/interfaces.js +2 -0
- package/dist_ts/plugins.d.ts +11 -0
- package/dist_ts/plugins.js +12 -0
- package/license.md +19 -0
- package/package.json +48 -0
- package/readme.md +199 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.auth.ts +321 -0
- package/ts/classes.config.ts +104 -0
- package/ts/classes.coremail.ts +249 -0
- package/ts/classes.desiredstate.ts +508 -0
- package/ts/classes.gateway.ts +811 -0
- package/ts/classes.inbound.ts +898 -0
- package/ts/classes.maintenance.ts +335 -0
- package/ts/classes.models.ts +530 -0
- package/ts/classes.server.ts +444 -0
- package/ts/classes.storage.ts +448 -0
- package/ts/classes.submissions.ts +554 -0
- package/ts/classes.transfer.ts +379 -0
- package/ts/coremail.cursor.ts +328 -0
- package/ts/coremail.log.ts +21 -0
- package/ts/coremail.mime.ts +94 -0
- package/ts/coremail.persistence.ts +1156 -0
- package/ts/coremail.quota.ts +214 -0
- package/ts/coremail.selectors.ts +35 -0
- package/ts/coremail.validation.ts +446 -0
- package/ts/index.ts +38 -0
- package/ts/interfaces.ts +109 -0
- package/ts/plugins.ts +11 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ICoreMailModels } from './classes.models.js';
|
|
2
|
+
import type { CoreMailStorage } from './classes.storage.js';
|
|
3
|
+
export declare class CoreMailMaintenanceService {
|
|
4
|
+
private readonly models;
|
|
5
|
+
private readonly storage;
|
|
6
|
+
private readonly now;
|
|
7
|
+
private sweepTimer;
|
|
8
|
+
private sweepTask;
|
|
9
|
+
private sweepController;
|
|
10
|
+
constructor(models: ICoreMailModels, storage: CoreMailStorage, now?: () => number);
|
|
11
|
+
start(): void;
|
|
12
|
+
stop(): Promise<void>;
|
|
13
|
+
sweep(signalArg?: AbortSignal): Promise<void>;
|
|
14
|
+
private purgeSubmission;
|
|
15
|
+
private runSweep;
|
|
16
|
+
}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { logCoreMailFailure } from './coremail.log.js';
|
|
3
|
+
const sweepIntervalMs = 60_000;
|
|
4
|
+
const batchSize = 100;
|
|
5
|
+
const transferRetirementGraceMs = plugins.serveZoneInterfaces.data.coreMailLimits.transferGrantTtlMs
|
|
6
|
+
+ plugins.serveZoneInterfaces.data.coreMailLimits.transferOverallTimeoutMs
|
|
7
|
+
+ 2 * 60_000;
|
|
8
|
+
export class CoreMailMaintenanceService {
|
|
9
|
+
models;
|
|
10
|
+
storage;
|
|
11
|
+
now;
|
|
12
|
+
sweepTimer = null;
|
|
13
|
+
sweepTask = null;
|
|
14
|
+
sweepController = null;
|
|
15
|
+
constructor(models, storage, now = Date.now) {
|
|
16
|
+
this.models = models;
|
|
17
|
+
this.storage = storage;
|
|
18
|
+
this.now = now;
|
|
19
|
+
}
|
|
20
|
+
start() {
|
|
21
|
+
if (this.sweepTimer)
|
|
22
|
+
return;
|
|
23
|
+
this.sweepTimer = setInterval(() => {
|
|
24
|
+
void this.runSweep();
|
|
25
|
+
}, sweepIntervalMs);
|
|
26
|
+
this.sweepTimer.unref?.();
|
|
27
|
+
}
|
|
28
|
+
async stop() {
|
|
29
|
+
if (this.sweepTimer) {
|
|
30
|
+
clearInterval(this.sweepTimer);
|
|
31
|
+
this.sweepTimer = null;
|
|
32
|
+
}
|
|
33
|
+
this.sweepController?.abort();
|
|
34
|
+
await this.sweepTask?.catch(() => undefined);
|
|
35
|
+
}
|
|
36
|
+
async sweep(signalArg) {
|
|
37
|
+
const now = this.now();
|
|
38
|
+
const terminalOutboundCutoff = now
|
|
39
|
+
- plugins.serveZoneInterfaces.data.coreMailRetentionPolicy.terminalOutboundMs;
|
|
40
|
+
const acknowledgedInboundCutoff = now
|
|
41
|
+
- plugins.serveZoneInterfaces.data.coreMailRetentionPolicy.acknowledgedInboundMs;
|
|
42
|
+
const idempotencyReceiptCutoff = now
|
|
43
|
+
- plugins.serveZoneInterfaces.data.coreMailRetentionPolicy.idempotencyReceiptMs;
|
|
44
|
+
const expiredCapabilityCutoff = now
|
|
45
|
+
- plugins.serveZoneInterfaces.data.coreMailRetentionPolicy.expiredCapabilityMs;
|
|
46
|
+
const transferRetirementCutoff = now - transferRetirementGraceMs;
|
|
47
|
+
while (!signalArg?.aborted) {
|
|
48
|
+
const terminalSubmissions = await this.models.Submission.exact.findStored({
|
|
49
|
+
filter: {
|
|
50
|
+
state: { $in: ['delivered', 'failed', 'deadLettered'] },
|
|
51
|
+
terminalAt: { $lte: terminalOutboundCutoff },
|
|
52
|
+
$or: [
|
|
53
|
+
{ retiringAt: { $exists: false } },
|
|
54
|
+
{ retiringAt: { $lte: transferRetirementCutoff } },
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
sort: { terminalAt: 1, submissionId: 1 },
|
|
58
|
+
limit: batchSize,
|
|
59
|
+
});
|
|
60
|
+
for (const submission of terminalSubmissions) {
|
|
61
|
+
signalArg?.throwIfAborted();
|
|
62
|
+
await this.purgeSubmission(submission, signalArg);
|
|
63
|
+
}
|
|
64
|
+
if (terminalSubmissions.length < batchSize)
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
while (!signalArg?.aborted) {
|
|
68
|
+
const abandonedSubmissions = await this.models.Submission.exact.findStored({
|
|
69
|
+
filter: {
|
|
70
|
+
state: { $in: ['preparing', 'uploading', 'ready'] },
|
|
71
|
+
updatedAt: { $lte: idempotencyReceiptCutoff },
|
|
72
|
+
$or: [
|
|
73
|
+
{ leaseExpiresAt: { $exists: false } },
|
|
74
|
+
{ leaseExpiresAt: { $lte: now } },
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
sort: { createdAt: 1, submissionId: 1 },
|
|
78
|
+
limit: batchSize,
|
|
79
|
+
});
|
|
80
|
+
for (const submission of abandonedSubmissions) {
|
|
81
|
+
signalArg?.throwIfAborted();
|
|
82
|
+
const retirement = await this.models.Submission.exact.transition({
|
|
83
|
+
current: submission,
|
|
84
|
+
change: (modelArg) => {
|
|
85
|
+
modelArg.state = 'failed';
|
|
86
|
+
modelArg.error = { code: 'STATE_CONFLICT', retryable: false };
|
|
87
|
+
modelArg.terminalAt = submission.updatedAt;
|
|
88
|
+
modelArg.retiringAt = now;
|
|
89
|
+
modelArg.updatedAt = now;
|
|
90
|
+
modelArg.revision += 1;
|
|
91
|
+
delete modelArg.nextAttemptAt;
|
|
92
|
+
delete modelArg.workerRetryAt;
|
|
93
|
+
delete modelArg.deliveredAt;
|
|
94
|
+
delete modelArg.leaseOwnerTaskId;
|
|
95
|
+
delete modelArg.leaseToken;
|
|
96
|
+
delete modelArg.leaseExpiresAt;
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
if (retirement.status !== 'transitioned')
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (abandonedSubmissions.length < batchSize)
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
while (!signalArg?.aborted) {
|
|
106
|
+
const deliveries = await this.models.InboundDelivery.exact.findStored({
|
|
107
|
+
filter: {
|
|
108
|
+
state: 'acknowledged',
|
|
109
|
+
updatedAt: { $lte: acknowledgedInboundCutoff },
|
|
110
|
+
},
|
|
111
|
+
sort: { updatedAt: 1, deliveryId: 1 },
|
|
112
|
+
limit: batchSize,
|
|
113
|
+
});
|
|
114
|
+
for (const delivery of deliveries) {
|
|
115
|
+
signalArg?.throwIfAborted();
|
|
116
|
+
const retainedReferences = await this.models.InboundDelivery.exact.count({
|
|
117
|
+
rawMimeObjectKey: delivery.rawMimeObjectKey,
|
|
118
|
+
deliveryId: { $ne: delivery.deliveryId },
|
|
119
|
+
$or: [
|
|
120
|
+
{ state: { $ne: 'acknowledged' } },
|
|
121
|
+
{ updatedAt: { $gt: acknowledgedInboundCutoff } },
|
|
122
|
+
],
|
|
123
|
+
});
|
|
124
|
+
if (retainedReferences === 0) {
|
|
125
|
+
await this.storage.purgeExact(delivery.rawMimeObjectKey, signalArg);
|
|
126
|
+
}
|
|
127
|
+
await this.models.InboundDelivery.exact.delete({ current: delivery });
|
|
128
|
+
}
|
|
129
|
+
if (deliveries.length < batchSize)
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
let handoffCursor;
|
|
133
|
+
while (!signalArg?.aborted) {
|
|
134
|
+
const incompleteHandoffs = await this.models.InboundHandoff.exact.findStored({
|
|
135
|
+
filter: {
|
|
136
|
+
$and: [
|
|
137
|
+
{
|
|
138
|
+
$or: [
|
|
139
|
+
{
|
|
140
|
+
state: { $in: ['prepared', 'uploaded', 'failed'] },
|
|
141
|
+
updatedAt: { $lte: idempotencyReceiptCutoff },
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
state: 'retiring',
|
|
145
|
+
retiringAt: { $lte: transferRetirementCutoff },
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
},
|
|
149
|
+
...(handoffCursor
|
|
150
|
+
? [{
|
|
151
|
+
$or: [
|
|
152
|
+
{ createdAt: { $gt: handoffCursor.createdAt } },
|
|
153
|
+
{
|
|
154
|
+
createdAt: handoffCursor.createdAt,
|
|
155
|
+
handoffId: { $gt: handoffCursor.handoffId },
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
}]
|
|
159
|
+
: []),
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
sort: { createdAt: 1, handoffId: 1 },
|
|
163
|
+
limit: batchSize,
|
|
164
|
+
});
|
|
165
|
+
for (const handoff of incompleteHandoffs) {
|
|
166
|
+
signalArg?.throwIfAborted();
|
|
167
|
+
let retiringHandoff = handoff;
|
|
168
|
+
if (handoff.state !== 'retiring') {
|
|
169
|
+
const retirement = await this.models.InboundHandoff.exact.transition({
|
|
170
|
+
current: handoff,
|
|
171
|
+
change: (modelArg) => {
|
|
172
|
+
modelArg.state = 'retiring';
|
|
173
|
+
modelArg.retiringAt = now;
|
|
174
|
+
modelArg.updatedAt = now;
|
|
175
|
+
modelArg.revision += 1;
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
if (retirement.status !== 'transitioned')
|
|
179
|
+
continue;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
const deliveryReferences = await this.models.InboundDelivery.exact.count({
|
|
183
|
+
rawMimeObjectKey: retiringHandoff.objectKey,
|
|
184
|
+
});
|
|
185
|
+
if (deliveryReferences === 0) {
|
|
186
|
+
await this.storage.purgeExact(retiringHandoff.objectKey, signalArg);
|
|
187
|
+
await this.models.InboundHandoff.exact.delete({ current: retiringHandoff });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
const lastHandoff = incompleteHandoffs.at(-1);
|
|
191
|
+
if (!lastHandoff || incompleteHandoffs.length < batchSize)
|
|
192
|
+
break;
|
|
193
|
+
handoffCursor = {
|
|
194
|
+
createdAt: lastHandoff.createdAt,
|
|
195
|
+
handoffId: lastHandoff.handoffId,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
while (!signalArg?.aborted) {
|
|
199
|
+
const completedHandoffs = await this.models.InboundHandoff.exact.findStored({
|
|
200
|
+
filter: {
|
|
201
|
+
state: 'completed',
|
|
202
|
+
completedAt: { $lte: idempotencyReceiptCutoff },
|
|
203
|
+
},
|
|
204
|
+
sort: { completedAt: 1, handoffId: 1 },
|
|
205
|
+
limit: batchSize,
|
|
206
|
+
});
|
|
207
|
+
for (const handoff of completedHandoffs) {
|
|
208
|
+
signalArg?.throwIfAborted();
|
|
209
|
+
await this.models.InboundHandoff.exact.delete({ current: handoff });
|
|
210
|
+
}
|
|
211
|
+
if (completedHandoffs.length < batchSize)
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
while (!signalArg?.aborted) {
|
|
215
|
+
const activeState = await this.models.State.exact.findStoredOne({
|
|
216
|
+
stateId: 'active',
|
|
217
|
+
});
|
|
218
|
+
const snapshots = await this.models.DesiredSnapshot.exact.findStored({
|
|
219
|
+
filter: {
|
|
220
|
+
$or: [
|
|
221
|
+
{
|
|
222
|
+
state: { $in: ['staged', 'superseded', 'failed'] },
|
|
223
|
+
updatedAt: { $lte: idempotencyReceiptCutoff },
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
state: 'retiring',
|
|
227
|
+
retiringAt: { $lte: transferRetirementCutoff },
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
...(activeState ? { snapshotId: { $ne: activeState.snapshotId } } : {}),
|
|
231
|
+
},
|
|
232
|
+
sort: { createdAt: 1, snapshotId: 1 },
|
|
233
|
+
limit: batchSize,
|
|
234
|
+
});
|
|
235
|
+
for (const snapshot of snapshots) {
|
|
236
|
+
signalArg?.throwIfAborted();
|
|
237
|
+
let retiringSnapshot = snapshot;
|
|
238
|
+
if (snapshot.state !== 'retiring') {
|
|
239
|
+
const retirement = await this.models.DesiredSnapshot.exact.transition({
|
|
240
|
+
current: snapshot,
|
|
241
|
+
change: (modelArg) => {
|
|
242
|
+
modelArg.state = 'retiring';
|
|
243
|
+
modelArg.retiringAt = now;
|
|
244
|
+
modelArg.updatedAt = now;
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
if (retirement.status !== 'transitioned')
|
|
248
|
+
continue;
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
await this.storage.purgeExact(retiringSnapshot.objectKey, signalArg);
|
|
252
|
+
await this.models.DesiredSnapshot.exact.delete({ current: retiringSnapshot });
|
|
253
|
+
}
|
|
254
|
+
if (snapshots.length < batchSize)
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
while (!signalArg?.aborted) {
|
|
258
|
+
const grants = await this.models.TransferGrant.exact.findStored({
|
|
259
|
+
filter: { expiresAt: { $lte: expiredCapabilityCutoff } },
|
|
260
|
+
sort: { expiresAt: 1, grantId: 1 },
|
|
261
|
+
limit: batchSize,
|
|
262
|
+
});
|
|
263
|
+
for (const grant of grants) {
|
|
264
|
+
signalArg?.throwIfAborted();
|
|
265
|
+
await this.models.TransferGrant.exact.delete({ current: grant });
|
|
266
|
+
}
|
|
267
|
+
if (grants.length < batchSize)
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
while (!signalArg?.aborted) {
|
|
271
|
+
const handles = await this.models.RecipientHandle.exact.findStored({
|
|
272
|
+
filter: { expiresAt: { $lte: expiredCapabilityCutoff } },
|
|
273
|
+
sort: { expiresAt: 1, routingHandle: 1 },
|
|
274
|
+
limit: batchSize,
|
|
275
|
+
});
|
|
276
|
+
for (const handle of handles) {
|
|
277
|
+
signalArg?.throwIfAborted();
|
|
278
|
+
await this.models.RecipientHandle.exact.delete({ current: handle });
|
|
279
|
+
}
|
|
280
|
+
if (handles.length < batchSize)
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
while (!signalArg?.aborted) {
|
|
284
|
+
const counters = await this.models.QuotaCounter.exact.findStored({
|
|
285
|
+
filter: {
|
|
286
|
+
updatedAt: { $lte: idempotencyReceiptCutoff },
|
|
287
|
+
$or: [{
|
|
288
|
+
kind: { $in: ['outbound-minute', 'outbound-day'] },
|
|
289
|
+
}, {
|
|
290
|
+
kind: 'pending-inbound',
|
|
291
|
+
count: 0,
|
|
292
|
+
}],
|
|
293
|
+
},
|
|
294
|
+
sort: { updatedAt: 1, counterId: 1 },
|
|
295
|
+
limit: batchSize,
|
|
296
|
+
});
|
|
297
|
+
for (const counter of counters) {
|
|
298
|
+
signalArg?.throwIfAborted();
|
|
299
|
+
await this.models.QuotaCounter.exact.delete({ current: counter });
|
|
300
|
+
}
|
|
301
|
+
if (counters.length < batchSize)
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async purgeSubmission(submissionArg, signalArg) {
|
|
306
|
+
const objectKeys = new Set(submissionArg.parts.map((partArg) => partArg.objectKey));
|
|
307
|
+
if (submissionArg.mimeObjectKey)
|
|
308
|
+
objectKeys.add(submissionArg.mimeObjectKey);
|
|
309
|
+
for (const objectKey of objectKeys) {
|
|
310
|
+
signalArg?.throwIfAborted();
|
|
311
|
+
await this.storage.purgeExact(objectKey, signalArg);
|
|
312
|
+
}
|
|
313
|
+
await this.models.Submission.exact.delete({ current: submissionArg });
|
|
314
|
+
}
|
|
315
|
+
async runSweep() {
|
|
316
|
+
if (this.sweepTask)
|
|
317
|
+
return await this.sweepTask;
|
|
318
|
+
const controller = new AbortController();
|
|
319
|
+
this.sweepController = controller;
|
|
320
|
+
const task = this.sweep(controller.signal).catch(async () => {
|
|
321
|
+
if (!controller.signal.aborted) {
|
|
322
|
+
await logCoreMailFailure('retention', 'SWEEP_FAILED').catch(() => undefined);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
this.sweepTask = task;
|
|
326
|
+
try {
|
|
327
|
+
await task;
|
|
328
|
+
}
|
|
329
|
+
finally {
|
|
330
|
+
if (this.sweepTask === task) {
|
|
331
|
+
this.sweepTask = null;
|
|
332
|
+
}
|
|
333
|
+
if (this.sweepController === controller) {
|
|
334
|
+
this.sweepController = null;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5tYWludGVuYW5jZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMubWFpbnRlbmFuY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFHeEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFdkQsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDO0FBQy9CLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQztBQUN0QixNQUFNLHlCQUF5QixHQUM3QixPQUFPLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxrQkFBa0I7TUFDaEUsT0FBTyxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsd0JBQXdCO01BQ3hFLENBQUMsR0FBRyxNQUFNLENBQUM7QUFFZixNQUFNLE9BQU8sMEJBQTBCO0lBTWxCO0lBQ0E7SUFDQTtJQVBYLFVBQVUsR0FBMEMsSUFBSSxDQUFDO0lBQ3pELFNBQVMsR0FBeUIsSUFBSSxDQUFDO0lBQ3ZDLGVBQWUsR0FBMkIsSUFBSSxDQUFDO0lBRXZELFlBQ21CLE1BQXVCLEVBQ3ZCLE9BQXdCLEVBQ3hCLE1BQW9CLElBQUksQ0FBQyxHQUFHO1FBRjVCLFdBQU0sR0FBTixNQUFNLENBQWlCO1FBQ3ZCLFlBQU8sR0FBUCxPQUFPLENBQWlCO1FBQ3hCLFFBQUcsR0FBSCxHQUFHLENBQXlCO0lBQzVDLENBQUM7SUFFRyxLQUFLO1FBQ1YsSUFBSSxJQUFJLENBQUMsVUFBVTtZQUFFLE9BQU87UUFDNUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO1lBQ2pDLEtBQUssSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3ZCLENBQUMsRUFBRSxlQUFlLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUM7SUFDNUIs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
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import type { ISubmissionPartRecord, TTransferGrantPurpose } from './interfaces.js';
|
|
3
|
+
import { type ICoreMailDesiredSnapshotRecord, type ICoreMailInboundDeliveryRecord, type ICoreMailInboundHandoffRecord, type ICoreMailQuotaCounterRecord, type ICoreMailRecipientHandleRecord, type ICoreMailStateRecord, type ICoreMailSubmissionRecord, type ICoreMailTransferGrantRecord } from './coremail.persistence.js';
|
|
4
|
+
type TCoreMailSha256 = plugins.serveZoneInterfaces.data.TCoreMailSha256;
|
|
5
|
+
export declare class CoreMailStateDoc extends plugins.smartdata.SmartDataDbDoc<CoreMailStateDoc, ICoreMailStateRecord> implements ICoreMailStateRecord {
|
|
6
|
+
static exact: plugins.smartdata.TExact<CoreMailStateDoc>;
|
|
7
|
+
stateId: string;
|
|
8
|
+
appliedConfigEpoch: number;
|
|
9
|
+
appliedDesiredStateDigest: TCoreMailSha256;
|
|
10
|
+
snapshotId: string;
|
|
11
|
+
updatedAt: number;
|
|
12
|
+
}
|
|
13
|
+
export declare class CoreMailDesiredSnapshotDoc extends plugins.smartdata.SmartDataDbDoc<CoreMailDesiredSnapshotDoc, ICoreMailDesiredSnapshotRecord> implements ICoreMailDesiredSnapshotRecord {
|
|
14
|
+
static exact: plugins.smartdata.TExact<CoreMailDesiredSnapshotDoc>;
|
|
15
|
+
snapshotId: string;
|
|
16
|
+
reconciliationId: string;
|
|
17
|
+
expectedAppliedConfigEpoch: number;
|
|
18
|
+
configEpoch: number;
|
|
19
|
+
desiredStateDigest: TCoreMailSha256;
|
|
20
|
+
lengthBytes: number;
|
|
21
|
+
objectKey: string;
|
|
22
|
+
state: 'staged' | 'active' | 'superseded' | 'failed' | 'retiring';
|
|
23
|
+
createdAt: number;
|
|
24
|
+
updatedAt: number;
|
|
25
|
+
activatedAt?: number;
|
|
26
|
+
retiringAt?: number;
|
|
27
|
+
errorCode?: plugins.serveZoneInterfaces.data.TCoreMailErrorCode;
|
|
28
|
+
}
|
|
29
|
+
export declare class CoreMailQuotaCounterDoc extends plugins.smartdata.SmartDataDbDoc<CoreMailQuotaCounterDoc, ICoreMailQuotaCounterRecord> implements ICoreMailQuotaCounterRecord {
|
|
30
|
+
static exact: plugins.smartdata.TExact<CoreMailQuotaCounterDoc>;
|
|
31
|
+
counterId: TCoreMailSha256;
|
|
32
|
+
tenantId: string;
|
|
33
|
+
serviceId: string;
|
|
34
|
+
bindingId: string;
|
|
35
|
+
bindingRevision: number;
|
|
36
|
+
kind: ICoreMailQuotaCounterRecord['kind'];
|
|
37
|
+
windowStartedAt?: number;
|
|
38
|
+
count: number;
|
|
39
|
+
createdAt: number;
|
|
40
|
+
updatedAt: number;
|
|
41
|
+
}
|
|
42
|
+
export declare class CoreMailTransferGrantDoc extends plugins.smartdata.SmartDataDbDoc<CoreMailTransferGrantDoc, ICoreMailTransferGrantRecord> implements ICoreMailTransferGrantRecord {
|
|
43
|
+
static exact: plugins.smartdata.TExact<CoreMailTransferGrantDoc>;
|
|
44
|
+
grantId: string;
|
|
45
|
+
authorityKind: 'control' | 'gateway' | 'workload';
|
|
46
|
+
tenantId: string;
|
|
47
|
+
serviceId: string;
|
|
48
|
+
bindingId: string;
|
|
49
|
+
purpose: TTransferGrantPurpose;
|
|
50
|
+
method: 'PUT' | 'GET';
|
|
51
|
+
path: string;
|
|
52
|
+
bearerSha256: TCoreMailSha256;
|
|
53
|
+
expectedSha256: TCoreMailSha256;
|
|
54
|
+
lengthBytes: number;
|
|
55
|
+
contentType: string;
|
|
56
|
+
objectKey: string;
|
|
57
|
+
state: 'issued' | 'transferring' | 'consumed' | 'failed' | 'expired';
|
|
58
|
+
expiresAt: number;
|
|
59
|
+
createdAt: number;
|
|
60
|
+
consumedAt?: number;
|
|
61
|
+
}
|
|
62
|
+
export declare class CoreMailSubmissionDoc extends plugins.smartdata.SmartDataDbDoc<CoreMailSubmissionDoc, ICoreMailSubmissionRecord> implements ICoreMailSubmissionRecord {
|
|
63
|
+
static exact: plugins.smartdata.TExact<CoreMailSubmissionDoc>;
|
|
64
|
+
submissionId: string;
|
|
65
|
+
tenantId: string;
|
|
66
|
+
serviceId: string;
|
|
67
|
+
bindingId: string;
|
|
68
|
+
bindingRevision: number;
|
|
69
|
+
revision: number;
|
|
70
|
+
idempotencyKey: string;
|
|
71
|
+
submissionDigest: TCoreMailSha256;
|
|
72
|
+
state: plugins.serveZoneInterfaces.data.TCoreMailSubmissionState;
|
|
73
|
+
message: plugins.serveZoneInterfaces.data.ICoreMailOutboundMessageDescriptor;
|
|
74
|
+
parts: ISubmissionPartRecord[];
|
|
75
|
+
mimeObjectKey?: string;
|
|
76
|
+
mimeSha256?: TCoreMailSha256;
|
|
77
|
+
mimeLengthBytes?: number;
|
|
78
|
+
mimePublishedAt?: number;
|
|
79
|
+
transportMessageId?: string;
|
|
80
|
+
transportGrantId?: string;
|
|
81
|
+
gatewayStatusUpdatedAt?: number;
|
|
82
|
+
attempts: number;
|
|
83
|
+
nextAttemptAt?: number;
|
|
84
|
+
workerRetryAt?: number;
|
|
85
|
+
retiringAt?: number;
|
|
86
|
+
leaseOwnerTaskId?: string;
|
|
87
|
+
leaseToken?: string;
|
|
88
|
+
leaseExpiresAt?: number;
|
|
89
|
+
acceptedAt?: number;
|
|
90
|
+
deliveredAt?: number;
|
|
91
|
+
terminalAt?: number;
|
|
92
|
+
error?: plugins.serveZoneInterfaces.data.ICoreMailErrorData;
|
|
93
|
+
createdAt: number;
|
|
94
|
+
updatedAt: number;
|
|
95
|
+
}
|
|
96
|
+
export declare class CoreMailInboundDeliveryDoc extends plugins.smartdata.SmartDataDbDoc<CoreMailInboundDeliveryDoc, ICoreMailInboundDeliveryRecord> implements ICoreMailInboundDeliveryRecord {
|
|
97
|
+
static exact: plugins.smartdata.TExact<CoreMailInboundDeliveryDoc>;
|
|
98
|
+
deliveryId: string;
|
|
99
|
+
tenantId: string;
|
|
100
|
+
serviceId: string;
|
|
101
|
+
bindingId: string;
|
|
102
|
+
bindingRevision: number;
|
|
103
|
+
revision: number;
|
|
104
|
+
transportDeliveryId: string;
|
|
105
|
+
state: plugins.serveZoneInterfaces.data.TCoreMailInboundDeliveryState;
|
|
106
|
+
envelope: plugins.serveZoneInterfaces.data.ICoreMailEnvelope;
|
|
107
|
+
rawMimeSha256: TCoreMailSha256;
|
|
108
|
+
rawMimeLengthBytes: number;
|
|
109
|
+
rawMimeObjectKey: string;
|
|
110
|
+
messageId?: string;
|
|
111
|
+
subject?: string;
|
|
112
|
+
receivedAt: number;
|
|
113
|
+
updatedAt: number;
|
|
114
|
+
fetchGrantId?: string;
|
|
115
|
+
acknowledgedOutcome?: plugins.serveZoneInterfaces.data.TCoreMailInboundAckOutcome;
|
|
116
|
+
}
|
|
117
|
+
export declare class CoreMailRecipientHandleDoc extends plugins.smartdata.SmartDataDbDoc<CoreMailRecipientHandleDoc, ICoreMailRecipientHandleRecord> implements ICoreMailRecipientHandleRecord {
|
|
118
|
+
static exact: plugins.smartdata.TExact<CoreMailRecipientHandleDoc>;
|
|
119
|
+
routingHandle: string;
|
|
120
|
+
tenantId: string;
|
|
121
|
+
serviceId: string;
|
|
122
|
+
bindingId: string;
|
|
123
|
+
bindingRevision: number;
|
|
124
|
+
maxPendingInbound: number;
|
|
125
|
+
recipient: string;
|
|
126
|
+
envelopeDigest: TCoreMailSha256;
|
|
127
|
+
state: 'issued' | 'consumed' | 'expired';
|
|
128
|
+
handoffId?: string;
|
|
129
|
+
expiresAt: number;
|
|
130
|
+
createdAt: number;
|
|
131
|
+
}
|
|
132
|
+
export declare class CoreMailInboundHandoffDoc extends plugins.smartdata.SmartDataDbDoc<CoreMailInboundHandoffDoc, ICoreMailInboundHandoffRecord> implements ICoreMailInboundHandoffRecord {
|
|
133
|
+
static exact: plugins.smartdata.TExact<CoreMailInboundHandoffDoc>;
|
|
134
|
+
handoffId: string;
|
|
135
|
+
revision: number;
|
|
136
|
+
transportDeliveryId: string;
|
|
137
|
+
routingHandles: string[];
|
|
138
|
+
message: plugins.serveZoneInterfaces.data.ICoreMailGatewayMessageDescriptor;
|
|
139
|
+
source: plugins.serveZoneInterfaces.data.IMailConnectionInfo;
|
|
140
|
+
state: 'prepared' | 'uploaded' | 'completed' | 'failed' | 'retiring';
|
|
141
|
+
objectKey: string;
|
|
142
|
+
grantId?: string;
|
|
143
|
+
deliveryIds: string[];
|
|
144
|
+
createdAt: number;
|
|
145
|
+
updatedAt: number;
|
|
146
|
+
completedAt?: number;
|
|
147
|
+
retiringAt?: number;
|
|
148
|
+
}
|
|
149
|
+
export interface ICoreMailModels {
|
|
150
|
+
State: typeof CoreMailStateDoc;
|
|
151
|
+
DesiredSnapshot: typeof CoreMailDesiredSnapshotDoc;
|
|
152
|
+
QuotaCounter: typeof CoreMailQuotaCounterDoc;
|
|
153
|
+
TransferGrant: typeof CoreMailTransferGrantDoc;
|
|
154
|
+
Submission: typeof CoreMailSubmissionDoc;
|
|
155
|
+
InboundDelivery: typeof CoreMailInboundDeliveryDoc;
|
|
156
|
+
RecipientHandle: typeof CoreMailRecipientHandleDoc;
|
|
157
|
+
InboundHandoff: typeof CoreMailInboundHandoffDoc;
|
|
158
|
+
}
|
|
159
|
+
export declare const createCoreMailModels: (dbArg: plugins.smartdata.SmartdataDb) => ICoreMailModels;
|
|
160
|
+
export declare const prepareCoreMailModelsForTransactions: (modelsArg: ICoreMailModels) => Promise<void>;
|
|
161
|
+
export {};
|