@byok-sdk/core 0.12.0 → 0.13.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/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/mailbox.d.ts +20 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1229,7 +1229,7 @@ var InMemoryMailboxStore = class {
|
|
|
1229
1229
|
const device = this.#devices.get(tenantKey(tenant, query.deviceId));
|
|
1230
1230
|
const limit = query.limit ?? DEFAULT_READ_LIMIT;
|
|
1231
1231
|
if (device === void 0) {
|
|
1232
|
-
return { messages: [], nextSeq: query.afterSeq, hasMore: false };
|
|
1232
|
+
return { messages: [], nextSeq: query.afterSeq, hasMore: false, recoverableFrom: 1 };
|
|
1233
1233
|
}
|
|
1234
1234
|
const pending = device.messages.filter((message) => message.state === "pending" && message.seq > query.afterSeq).sort((left, right) => left.seq - right.seq);
|
|
1235
1235
|
const page = pending.slice(0, limit);
|
|
@@ -1239,7 +1239,11 @@ var InMemoryMailboxStore = class {
|
|
|
1239
1239
|
// Reading is not acknowledging: the returned position is a *read* cursor.
|
|
1240
1240
|
// Nothing above was mutated, so an identical call replays the same page.
|
|
1241
1241
|
nextSeq: last?.seq ?? query.afterSeq,
|
|
1242
|
-
hasMore: pending.length > page.length
|
|
1242
|
+
hasMore: pending.length > page.length,
|
|
1243
|
+
// Computed over the WHOLE mailbox, not the queried slice: the floor is a
|
|
1244
|
+
// property of the device's history, and reporting it relative to
|
|
1245
|
+
// `afterSeq` would make every cursor look recoverable from itself.
|
|
1246
|
+
recoverableFrom: this.#recoverableFrom(device)
|
|
1243
1247
|
};
|
|
1244
1248
|
}
|
|
1245
1249
|
async advanceCursor(tenant, input) {
|
|
@@ -1345,6 +1349,22 @@ var InMemoryMailboxStore = class {
|
|
|
1345
1349
|
this.#devices.set(key, created);
|
|
1346
1350
|
return created;
|
|
1347
1351
|
}
|
|
1352
|
+
/**
|
|
1353
|
+
* One past the highest row this device lost, which is exactly the highest
|
|
1354
|
+
* `expired` seq: dead-lettered rows are kept rather than deleted (§12.7.5),
|
|
1355
|
+
* so the loss stays observable and needs no column of its own to remember it.
|
|
1356
|
+
*
|
|
1357
|
+
* `acked` is deliberately not counted. A consumed row is not a lost one, and
|
|
1358
|
+
* counting it would turn a daemon re-polling from an old cursor — which the
|
|
1359
|
+
* at-least-once contract explicitly allows — into a hard failure.
|
|
1360
|
+
*/
|
|
1361
|
+
#recoverableFrom(device) {
|
|
1362
|
+
let lost = 0;
|
|
1363
|
+
for (const message of device.messages) {
|
|
1364
|
+
if (message.state === "expired" && message.seq > lost) lost = message.seq;
|
|
1365
|
+
}
|
|
1366
|
+
return lost + 1;
|
|
1367
|
+
}
|
|
1348
1368
|
#cursorState(tenant, deviceId, device) {
|
|
1349
1369
|
return {
|
|
1350
1370
|
tenantId: tenant,
|