@loro-dev/streams-crdt 0.16.1 → 0.16.2
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/README.md +24 -4
- package/dist/flock.d.ts +2 -2
- package/dist/flock.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/loro.d.ts +2 -2
- package/dist/loro.js +1 -1
- package/dist/{stream-id-DEOH5LmQ.d.ts → shared-C5Dyx541.d.ts} +26 -10
- package/dist/{stream-id-BERJQKYV.js → stream-id-Dlnc1PNH.js} +294 -74
- package/dist/stream-id-Dlnc1PNH.js.map +1 -0
- package/package.json +2 -2
- package/dist/stream-id-BERJQKYV.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StreamsClient, decodeSsePayload, readSseEvents } from "@loro-dev/streams-client";
|
|
1
|
+
import { StreamsClient, decodeSsePayload, readSseEvents, thrownToStreamError } from "@loro-dev/streams-client";
|
|
2
2
|
//#region src/deque.ts
|
|
3
3
|
const DEFAULT_COMPACT_THRESHOLD = 64;
|
|
4
4
|
const DEFAULT_MIN_CAPACITY = 16;
|
|
@@ -171,6 +171,51 @@ function computeRetryDelay(attempt, config = DEFAULT_RECONNECT_CONFIG, minDelayM
|
|
|
171
171
|
return applyJitter(typeof minDelayMs === "number" && minDelayMs > scheduled ? minDelayMs : scheduled, jitterFraction);
|
|
172
172
|
}
|
|
173
173
|
//#endregion
|
|
174
|
+
//#region src/error-context.ts
|
|
175
|
+
const contexts = /* @__PURE__ */ new WeakMap();
|
|
176
|
+
var ThrownValue = class extends Error {
|
|
177
|
+
constructor(original) {
|
|
178
|
+
super("Local operation failed");
|
|
179
|
+
this.original = original;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
function errorContext(error) {
|
|
183
|
+
return typeof error === "object" && error != null ? contexts.get(error) : void 0;
|
|
184
|
+
}
|
|
185
|
+
function originalThrown(error) {
|
|
186
|
+
return error instanceof ThrownValue ? error.original : error;
|
|
187
|
+
}
|
|
188
|
+
function recordErrorContext(error, context, replace = false) {
|
|
189
|
+
const tagged = typeof error === "object" && error != null ? error : new ThrownValue(error);
|
|
190
|
+
contexts.set(tagged, replace ? context : {
|
|
191
|
+
...context,
|
|
192
|
+
...contexts.get(tagged)
|
|
193
|
+
});
|
|
194
|
+
return tagged;
|
|
195
|
+
}
|
|
196
|
+
async function atErrorBoundary(context, task) {
|
|
197
|
+
const startedAt = Date.now();
|
|
198
|
+
try {
|
|
199
|
+
return await task();
|
|
200
|
+
} catch (error) {
|
|
201
|
+
throw recordErrorContext(error, {
|
|
202
|
+
...context,
|
|
203
|
+
elapsedMs: Math.max(0, Date.now() - startedAt)
|
|
204
|
+
}, context.source != null);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function atSyncErrorBoundary(context, task) {
|
|
208
|
+
const startedAt = Date.now();
|
|
209
|
+
try {
|
|
210
|
+
return task();
|
|
211
|
+
} catch (error) {
|
|
212
|
+
throw recordErrorContext(error, {
|
|
213
|
+
...context,
|
|
214
|
+
elapsedMs: Math.max(0, Date.now() - startedAt)
|
|
215
|
+
}, context.source != null);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
174
219
|
//#region src/items.ts
|
|
175
220
|
const BINARY_CONTENT_TYPE = "application/octet-stream";
|
|
176
221
|
function encodeItems(items) {
|
|
@@ -698,7 +743,7 @@ function classifyFetchError(err) {
|
|
|
698
743
|
retriable: true,
|
|
699
744
|
atMs: Date.now()
|
|
700
745
|
};
|
|
701
|
-
if (err
|
|
746
|
+
if (errorContext(err)?.originalCode === "network_error") return {
|
|
702
747
|
code: "network",
|
|
703
748
|
message,
|
|
704
749
|
retriable: true,
|
|
@@ -720,7 +765,33 @@ function classifyFetchError(err) {
|
|
|
720
765
|
function isStreamNotFoundError(error) {
|
|
721
766
|
return error instanceof HttpError && error.status === 404;
|
|
722
767
|
}
|
|
723
|
-
function toTransportError(error) {
|
|
768
|
+
function toTransportError(error, operation = "unknown") {
|
|
769
|
+
const evidence = errorContext(error);
|
|
770
|
+
const result = classifyTransportError(originalThrown(error), evidence?.originalCode === "network_error");
|
|
771
|
+
const source = isPayloadProtectionError(error) ? "payload_protection" : evidence?.source ?? (error instanceof AuthProviderError ? "auth" : error instanceof HttpError ? "http" : "unknown");
|
|
772
|
+
return {
|
|
773
|
+
...result,
|
|
774
|
+
context: {
|
|
775
|
+
stage: "unknown",
|
|
776
|
+
originalCode: result.code,
|
|
777
|
+
...error instanceof HttpError && { status: error.status },
|
|
778
|
+
...error instanceof TimeoutError && {
|
|
779
|
+
phase: error.timeoutType,
|
|
780
|
+
timeoutMs: error.timeoutMs
|
|
781
|
+
},
|
|
782
|
+
...error instanceof InitialSyncTimeoutError && {
|
|
783
|
+
stage: "initial_sync",
|
|
784
|
+
timeoutMs: error.timeoutMs,
|
|
785
|
+
elapsedMs: error.elapsedMs
|
|
786
|
+
},
|
|
787
|
+
...evidence,
|
|
788
|
+
source,
|
|
789
|
+
retryable: result.retryable,
|
|
790
|
+
operation
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
function classifyTransportError(error, fromFetch) {
|
|
724
795
|
if (isCrdtApplyIncompleteError(error)) return {
|
|
725
796
|
code: "apply_incomplete",
|
|
726
797
|
retryable: true,
|
|
@@ -810,10 +881,10 @@ function toTransportError(error) {
|
|
|
810
881
|
reason: error.reason,
|
|
811
882
|
message: payloadProtectionFailureMessage(error.reason)
|
|
812
883
|
};
|
|
813
|
-
if (
|
|
884
|
+
if (fromFetch) return {
|
|
814
885
|
code: "network_error",
|
|
815
886
|
retryable: true,
|
|
816
|
-
message: error.message
|
|
887
|
+
message: error instanceof Error ? error.message : "Fetch failed"
|
|
817
888
|
};
|
|
818
889
|
if (error instanceof Error) return {
|
|
819
890
|
code: "internal_error",
|
|
@@ -1057,7 +1128,10 @@ var StreamsTransportClient = class {
|
|
|
1057
1128
|
return "large-post";
|
|
1058
1129
|
}
|
|
1059
1130
|
async createStreamRequest() {
|
|
1060
|
-
const adapterHeaders = this.adapter.getCreateStreamHeaders ? await
|
|
1131
|
+
const adapterHeaders = this.adapter.getCreateStreamHeaders ? await atErrorBoundary({
|
|
1132
|
+
source: "crdt",
|
|
1133
|
+
stage: "crdt_export"
|
|
1134
|
+
}, this.adapter.getCreateStreamHeaders.bind(this.adapter)) : void 0;
|
|
1061
1135
|
const result = await this.client.create({
|
|
1062
1136
|
headers: adapterHeaders,
|
|
1063
1137
|
ttlSeconds: this.streamTtlSeconds
|
|
@@ -1246,7 +1320,7 @@ var StreamsTransportClient = class {
|
|
|
1246
1320
|
const dataEncoding = response.headers.get("Stream-SSE-Data-Encoding") ?? void 0;
|
|
1247
1321
|
const consume = async () => {
|
|
1248
1322
|
let sawBootstrap = false;
|
|
1249
|
-
for await (const event of readSseEvents(response.body, { onActivity })) {
|
|
1323
|
+
for await (const event of this.translateSseEvents(readSseEvents(response.body, { onActivity }))) {
|
|
1250
1324
|
if (!sawBootstrap) {
|
|
1251
1325
|
if (event.event !== "bootstrap") throw new ProtocolError(`ephemeral sse must start with bootstrap, got '${event.event}'`);
|
|
1252
1326
|
await onBootstrap(decodeSsePayload(event.data, dataEncoding));
|
|
@@ -1302,10 +1376,13 @@ var StreamsTransportClient = class {
|
|
|
1302
1376
|
controller.abort(new TimeoutError(phase, timeoutMs));
|
|
1303
1377
|
}, timeoutMs);
|
|
1304
1378
|
try {
|
|
1305
|
-
return await
|
|
1379
|
+
return await atErrorBoundary({
|
|
1380
|
+
source: "fetch",
|
|
1381
|
+
originalCode: "network_error"
|
|
1382
|
+
}, () => this.fetchImpl(input, {
|
|
1306
1383
|
...init,
|
|
1307
1384
|
signal
|
|
1308
|
-
});
|
|
1385
|
+
}));
|
|
1309
1386
|
} catch (error) {
|
|
1310
1387
|
if (controller.signal.aborted && controller.signal.reason instanceof TimeoutError) throw controller.signal.reason;
|
|
1311
1388
|
throw error;
|
|
@@ -1358,7 +1435,30 @@ var StreamsTransportClient = class {
|
|
|
1358
1435
|
target.searchParams.set("live", "sse");
|
|
1359
1436
|
return target.toString();
|
|
1360
1437
|
}
|
|
1438
|
+
async *translateSseEvents(events) {
|
|
1439
|
+
try {
|
|
1440
|
+
yield* events;
|
|
1441
|
+
} catch (error) {
|
|
1442
|
+
throw this.toTransportFailure(thrownToStreamError(error, "live-sse"));
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1361
1445
|
toTransportFailure(error) {
|
|
1446
|
+
const failure = this.convertTransportFailure(error);
|
|
1447
|
+
if (!(failure instanceof InitialSyncTimeoutError)) {
|
|
1448
|
+
const { operation, ...context } = error.context ?? {
|
|
1449
|
+
source: "unknown",
|
|
1450
|
+
operation: "unknown",
|
|
1451
|
+
originalCode: error.code
|
|
1452
|
+
};
|
|
1453
|
+
recordErrorContext(failure, {
|
|
1454
|
+
...context,
|
|
1455
|
+
requestOperation: operation,
|
|
1456
|
+
stage: operation === "bootstrap" ? "bootstrap" : operation === "read-once" ? "catch_up" : operation === "append" || operation === "append-cas" ? "upload" : "unknown"
|
|
1457
|
+
}, true);
|
|
1458
|
+
}
|
|
1459
|
+
return failure;
|
|
1460
|
+
}
|
|
1461
|
+
convertTransportFailure(error) {
|
|
1362
1462
|
switch (error.code) {
|
|
1363
1463
|
case "bad_request":
|
|
1364
1464
|
case "unauthorized":
|
|
@@ -1366,13 +1466,16 @@ var StreamsTransportClient = class {
|
|
|
1366
1466
|
case "not_found":
|
|
1367
1467
|
case "conflict":
|
|
1368
1468
|
case "gone":
|
|
1369
|
-
case "rate_limited": return new HttpError(error.message, error.status, {
|
|
1370
|
-
|
|
1371
|
-
|
|
1469
|
+
case "rate_limited": return new HttpError(error.message, error.status, {
|
|
1470
|
+
body: error.bodyText,
|
|
1471
|
+
requestId: error.context?.requestId
|
|
1472
|
+
});
|
|
1473
|
+
case "timeout": return new TimeoutError(error.phase, error.context?.timeoutMs ?? (error.phase === "poll" ? this.reconnectConfig.pollTimeoutMs : this.reconnectConfig.connectTimeoutMs));
|
|
1474
|
+
case "network_error": return error.cause instanceof Error ? error.cause : new TypeError(error.message);
|
|
1372
1475
|
case "protocol_error": return new ProtocolError(error.message, error.status);
|
|
1373
1476
|
case "unknown":
|
|
1374
1477
|
if (typeof error.status === "number") return new HttpError(error.message, error.status, {
|
|
1375
|
-
requestId: extractRequestIdFromHeaders(error.headers),
|
|
1478
|
+
requestId: error.context?.requestId ?? extractRequestIdFromHeaders(error.headers),
|
|
1376
1479
|
retryAfterMs: parseRetryAfterMs(error.headers?.["retry-after"]),
|
|
1377
1480
|
body: error.bodyText
|
|
1378
1481
|
});
|
|
@@ -1441,7 +1544,7 @@ var StreamsTransportClient = class {
|
|
|
1441
1544
|
latestCursor,
|
|
1442
1545
|
paused: false
|
|
1443
1546
|
};
|
|
1444
|
-
for await (const event of session.events) {
|
|
1547
|
+
for await (const event of this.translateSseEvents(session.events)) {
|
|
1445
1548
|
if (event.event === "data") {
|
|
1446
1549
|
pendingDataEvents.push(event.data);
|
|
1447
1550
|
continue;
|
|
@@ -2036,11 +2139,17 @@ async function persistRemoteCursor(input) {
|
|
|
2036
2139
|
...input.cursor,
|
|
2037
2140
|
updatedAtMs: (input.now ?? Date.now)()
|
|
2038
2141
|
};
|
|
2039
|
-
if (input.beforeRemoteCursorSave != null) await
|
|
2142
|
+
if (input.beforeRemoteCursorSave != null) await atErrorBoundary({
|
|
2143
|
+
source: "durability_hook",
|
|
2144
|
+
stage: "durability_hook"
|
|
2145
|
+
}, input.beforeRemoteCursorSave.bind(void 0, {
|
|
2040
2146
|
cursor: next,
|
|
2041
2147
|
source: input.source
|
|
2042
|
-
});
|
|
2043
|
-
await
|
|
2148
|
+
}));
|
|
2149
|
+
await atErrorBoundary({
|
|
2150
|
+
source: "cursor_store",
|
|
2151
|
+
stage: "cursor_save"
|
|
2152
|
+
}, () => input.remoteCursorStore.save(next));
|
|
2044
2153
|
return next;
|
|
2045
2154
|
}
|
|
2046
2155
|
function key(streamUrl) {
|
|
@@ -2270,14 +2379,24 @@ var TransportCursorManager = class {
|
|
|
2270
2379
|
let unresolved = [];
|
|
2271
2380
|
if (snapshot.byteLength > 0) {
|
|
2272
2381
|
if (typeof snapshotOffset !== "string" || snapshotOffset.length === 0 || snapshotOffset.length > 1024 || snapshotOffset === "now" || snapshotOffset === "-1") throw new Error("bootstrap snapshot offset does not match an admitted continuation");
|
|
2273
|
-
const
|
|
2382
|
+
const clearSnapshot = this.decodeSnapshot == null ? snapshot : await atErrorBoundary({
|
|
2383
|
+
source: "local",
|
|
2384
|
+
stage: "payload_decode"
|
|
2385
|
+
}, this.decodeSnapshot.bind(this, snapshot, snapshotOffset));
|
|
2386
|
+
const outcome = normalizeApplyReturn(await atErrorBoundary({
|
|
2387
|
+
source: "crdt",
|
|
2388
|
+
stage: "crdt_apply"
|
|
2389
|
+
}, () => this.adapter.applySnapshot(clearSnapshot)));
|
|
2274
2390
|
nextVersion = outcome.version;
|
|
2275
2391
|
complete = outcome.complete;
|
|
2276
2392
|
unresolved = outcome.unresolved ?? [];
|
|
2277
2393
|
}
|
|
2278
2394
|
const clearUpdates = await this.decodeRemoteUpdateItems(updates);
|
|
2279
2395
|
if (clearUpdates.length > 0) {
|
|
2280
|
-
const outcome = normalizeApplyReturn(await
|
|
2396
|
+
const outcome = normalizeApplyReturn(await atErrorBoundary({
|
|
2397
|
+
source: "crdt",
|
|
2398
|
+
stage: "crdt_apply"
|
|
2399
|
+
}, async () => this.adapter.applyRemoteUpdates(clearUpdates, nextVersion)));
|
|
2281
2400
|
nextVersion = outcome.version;
|
|
2282
2401
|
complete = outcome.complete;
|
|
2283
2402
|
unresolved = outcome.unresolved ?? [];
|
|
@@ -2305,7 +2424,10 @@ var TransportCursorManager = class {
|
|
|
2305
2424
|
let unresolved = this.incompleteCursors.get(cursor) ?? [];
|
|
2306
2425
|
const clearUpdates = await this.decodeRemoteUpdateItems(result.updates);
|
|
2307
2426
|
if (clearUpdates.length > 0) {
|
|
2308
|
-
const outcome = normalizeApplyReturn(await
|
|
2427
|
+
const outcome = normalizeApplyReturn(await atErrorBoundary({
|
|
2428
|
+
source: "crdt",
|
|
2429
|
+
stage: "crdt_apply"
|
|
2430
|
+
}, async () => this.adapter.applyRemoteUpdates(clearUpdates, nextVersion)));
|
|
2309
2431
|
nextVersion = outcome.version;
|
|
2310
2432
|
complete = outcome.complete;
|
|
2311
2433
|
unresolved = outcome.unresolved ?? [];
|
|
@@ -2324,7 +2446,10 @@ var TransportCursorManager = class {
|
|
|
2324
2446
|
let unresolved = this.incompleteCursors.get(cursor) ?? [];
|
|
2325
2447
|
const clearUpdates = await this.decodeRemoteUpdateItems(updates);
|
|
2326
2448
|
if (clearUpdates.length > 0) {
|
|
2327
|
-
const outcome = normalizeApplyReturn(await
|
|
2449
|
+
const outcome = normalizeApplyReturn(await atErrorBoundary({
|
|
2450
|
+
source: "crdt",
|
|
2451
|
+
stage: "crdt_apply"
|
|
2452
|
+
}, async () => this.adapter.applyRemoteUpdates(clearUpdates, nextVersion)));
|
|
2328
2453
|
nextVersion = outcome.version;
|
|
2329
2454
|
complete = outcome.complete;
|
|
2330
2455
|
unresolved = outcome.unresolved ?? [];
|
|
@@ -2346,7 +2471,10 @@ var TransportCursorManager = class {
|
|
|
2346
2471
|
}
|
|
2347
2472
|
async decodeRemoteUpdateItems(items) {
|
|
2348
2473
|
if (items.length === 0) return [];
|
|
2349
|
-
return this.decodeUpdateItems == null ? [...items] : await
|
|
2474
|
+
return this.decodeUpdateItems == null ? [...items] : await atErrorBoundary({
|
|
2475
|
+
source: "local",
|
|
2476
|
+
stage: "payload_decode"
|
|
2477
|
+
}, this.decodeUpdateItems.bind(this, items));
|
|
2350
2478
|
}
|
|
2351
2479
|
};
|
|
2352
2480
|
//#endregion
|
|
@@ -2453,8 +2581,14 @@ var TransportSnapshotManager = class {
|
|
|
2453
2581
|
}
|
|
2454
2582
|
if (tailBytes <= snapshotBytes) return;
|
|
2455
2583
|
if (tailBytes - snapshotBytes < config.minBytesSinceRemoteSnapshot) return;
|
|
2456
|
-
const snapshot =
|
|
2457
|
-
|
|
2584
|
+
const snapshot = atSyncErrorBoundary({
|
|
2585
|
+
source: "crdt",
|
|
2586
|
+
stage: "crdt_export"
|
|
2587
|
+
}, () => this.adapter.exportSnapshot());
|
|
2588
|
+
await this.putSnapshotAt(state.cursor.nextOffset, this.encodeSnapshot == null ? snapshot : await atErrorBoundary({
|
|
2589
|
+
source: "local",
|
|
2590
|
+
stage: "payload_encode"
|
|
2591
|
+
}, this.encodeSnapshot.bind(this, snapshot, state.cursor.nextOffset)));
|
|
2458
2592
|
} catch (error) {
|
|
2459
2593
|
this.logError("snapshot upload failed", error);
|
|
2460
2594
|
}
|
|
@@ -2681,7 +2815,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2681
2815
|
state.started = this.startJoin(state);
|
|
2682
2816
|
state.started.catch((error) => {
|
|
2683
2817
|
if (state.closed) return;
|
|
2684
|
-
const transportError = toTransportError(error);
|
|
2818
|
+
const transportError = toTransportError(error, "live");
|
|
2685
2819
|
if (transportError.retryable) {
|
|
2686
2820
|
state.initialSyncFailed = true;
|
|
2687
2821
|
state.lastError = transportError;
|
|
@@ -2739,7 +2873,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2739
2873
|
} catch (error) {
|
|
2740
2874
|
return {
|
|
2741
2875
|
ok: false,
|
|
2742
|
-
error: toTransportError(error)
|
|
2876
|
+
error: toTransportError(error, "snapshot")
|
|
2743
2877
|
};
|
|
2744
2878
|
}
|
|
2745
2879
|
}
|
|
@@ -2751,10 +2885,19 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2751
2885
|
*/
|
|
2752
2886
|
async uploadSnapshotForTesting() {
|
|
2753
2887
|
try {
|
|
2754
|
-
await
|
|
2888
|
+
await atErrorBoundary({
|
|
2889
|
+
source: "crdt",
|
|
2890
|
+
stage: "crdt_export"
|
|
2891
|
+
}, () => this.adapter.flushLocalExports?.());
|
|
2755
2892
|
const cursor = await this.syncOnce("sync");
|
|
2756
|
-
const rawSnapshot =
|
|
2757
|
-
|
|
2893
|
+
const rawSnapshot = atSyncErrorBoundary({
|
|
2894
|
+
source: "crdt",
|
|
2895
|
+
stage: "crdt_export"
|
|
2896
|
+
}, () => this.adapter.exportSnapshot());
|
|
2897
|
+
const snapshot = this.encodeSnapshot == null ? rawSnapshot : await atErrorBoundary({
|
|
2898
|
+
source: "local",
|
|
2899
|
+
stage: "payload_encode"
|
|
2900
|
+
}, this.encodeSnapshot.bind(this, rawSnapshot, cursor.nextOffset));
|
|
2758
2901
|
await this.client.putSnapshotAt(cursor.nextOffset, snapshot);
|
|
2759
2902
|
return {
|
|
2760
2903
|
ok: true,
|
|
@@ -2766,7 +2909,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2766
2909
|
} catch (error) {
|
|
2767
2910
|
return {
|
|
2768
2911
|
ok: false,
|
|
2769
|
-
error: toTransportError(error)
|
|
2912
|
+
error: toTransportError(error, "snapshot")
|
|
2770
2913
|
};
|
|
2771
2914
|
}
|
|
2772
2915
|
}
|
|
@@ -2782,7 +2925,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2782
2925
|
} catch (error) {
|
|
2783
2926
|
return {
|
|
2784
2927
|
ok: false,
|
|
2785
|
-
error: toTransportError(error)
|
|
2928
|
+
error: toTransportError(error, "create")
|
|
2786
2929
|
};
|
|
2787
2930
|
}
|
|
2788
2931
|
}
|
|
@@ -2796,7 +2939,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2796
2939
|
ok: true,
|
|
2797
2940
|
value: { deleted: await this.enqueueExclusive(async () => {
|
|
2798
2941
|
const deleted = await this.client.deleteStreamRequest();
|
|
2799
|
-
await
|
|
2942
|
+
await atErrorBoundary({
|
|
2943
|
+
source: "cursor_store",
|
|
2944
|
+
stage: "cursor_delete"
|
|
2945
|
+
}, () => this.remoteCursorStore.delete?.(this.streamUrl));
|
|
2800
2946
|
this.producerEpoch = 0;
|
|
2801
2947
|
this.nextProducerSeq = 0;
|
|
2802
2948
|
this.frozenLocalAppend = void 0;
|
|
@@ -2808,7 +2954,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2808
2954
|
} catch (error) {
|
|
2809
2955
|
return {
|
|
2810
2956
|
ok: false,
|
|
2811
|
-
error: toTransportError(error)
|
|
2957
|
+
error: toTransportError(error, "delete")
|
|
2812
2958
|
};
|
|
2813
2959
|
}
|
|
2814
2960
|
}
|
|
@@ -2825,7 +2971,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2825
2971
|
} catch (error) {
|
|
2826
2972
|
return {
|
|
2827
2973
|
ok: false,
|
|
2828
|
-
error: toTransportError(error)
|
|
2974
|
+
error: toTransportError(error, "sync")
|
|
2829
2975
|
};
|
|
2830
2976
|
}
|
|
2831
2977
|
}
|
|
@@ -2853,7 +2999,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2853
2999
|
} catch (error) {
|
|
2854
3000
|
return {
|
|
2855
3001
|
ok: false,
|
|
2856
|
-
error: toTransportError(error)
|
|
3002
|
+
error: toTransportError(error, "catchup")
|
|
2857
3003
|
};
|
|
2858
3004
|
}
|
|
2859
3005
|
}
|
|
@@ -2868,7 +3014,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2868
3014
|
return await this.enqueueExclusive(async () => {
|
|
2869
3015
|
try {
|
|
2870
3016
|
if (this.writeOnlyDisabledReason != null) throw new Error(this.writeOnlyDisabledReason);
|
|
2871
|
-
await
|
|
3017
|
+
await atErrorBoundary({
|
|
3018
|
+
source: "crdt",
|
|
3019
|
+
stage: "crdt_export"
|
|
3020
|
+
}, () => this.adapter.flushLocalExports?.());
|
|
2872
3021
|
const drained = await this.drainPendingWriteOnlyBatch();
|
|
2873
3022
|
if (drained == null) return {
|
|
2874
3023
|
ok: true,
|
|
@@ -2893,7 +3042,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2893
3042
|
} catch (error) {
|
|
2894
3043
|
return {
|
|
2895
3044
|
ok: false,
|
|
2896
|
-
error: toTransportError(error)
|
|
3045
|
+
error: toTransportError(error, "upload")
|
|
2897
3046
|
};
|
|
2898
3047
|
}
|
|
2899
3048
|
});
|
|
@@ -2918,14 +3067,17 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2918
3067
|
} catch (error) {
|
|
2919
3068
|
return {
|
|
2920
3069
|
ok: false,
|
|
2921
|
-
error: toTransportError(error)
|
|
3070
|
+
error: toTransportError(error, "join")
|
|
2922
3071
|
};
|
|
2923
3072
|
}
|
|
2924
3073
|
}
|
|
2925
3074
|
const state = createJoinState(createInitialRemoteCursor({
|
|
2926
3075
|
streamUrl: this.streamUrl,
|
|
2927
3076
|
nextOffset: "-1",
|
|
2928
|
-
serverLowerBoundVersion:
|
|
3077
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3078
|
+
source: "crdt",
|
|
3079
|
+
stage: "crdt_export"
|
|
3080
|
+
}, () => this.adapter.emptyVersion())
|
|
2929
3081
|
}));
|
|
2930
3082
|
const statusListener = params?.onStatusChange;
|
|
2931
3083
|
if (statusListener != null) state.statusListeners.add(statusListener);
|
|
@@ -2938,7 +3090,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
2938
3090
|
value: this.createSubscription(state, params)
|
|
2939
3091
|
};
|
|
2940
3092
|
} catch (error) {
|
|
2941
|
-
const transportError = toTransportError(error);
|
|
3093
|
+
const transportError = toTransportError(error, "join");
|
|
2942
3094
|
if (transportError.retryable && !state.closed) {
|
|
2943
3095
|
state.initialSyncFailed = true;
|
|
2944
3096
|
state.lastError = transportError;
|
|
@@ -3008,7 +3160,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3008
3160
|
if (state.readSubStatus === "connecting") try {
|
|
3009
3161
|
await state.started;
|
|
3010
3162
|
} catch (error) {
|
|
3011
|
-
const te = toTransportError(error);
|
|
3163
|
+
const te = toTransportError(error, "join");
|
|
3012
3164
|
throw new Error(te.code ? `initial sync failed: ${te.code}` : "initial sync failed");
|
|
3013
3165
|
}
|
|
3014
3166
|
if (state.writeSubStatus === "error") {
|
|
@@ -3016,7 +3168,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3016
3168
|
const msg = state.lastError?.code ? `local append failed: ${state.lastError.code}` : "local append failed";
|
|
3017
3169
|
throw new Error(msg);
|
|
3018
3170
|
}
|
|
3019
|
-
await
|
|
3171
|
+
await atErrorBoundary({
|
|
3172
|
+
source: "crdt",
|
|
3173
|
+
stage: "crdt_export"
|
|
3174
|
+
}, () => this.adapter.flushLocalExports?.());
|
|
3020
3175
|
if (state.closed) throw new Error("subscription closed");
|
|
3021
3176
|
const remaining = state.pendingLocal.length;
|
|
3022
3177
|
if (remaining === 0) return;
|
|
@@ -3059,6 +3214,11 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3059
3214
|
if (typeof hardTimeoutMs === "number" && Number.isFinite(hardTimeoutMs) && hardTimeoutMs > 0) hardTimeoutPromise = new Promise((_, reject) => {
|
|
3060
3215
|
hardTimer = setTimeout(() => {
|
|
3061
3216
|
hardTimeoutError = new InitialSyncTimeoutError(operation, hardTimeoutMs, Date.now() - startedAtMs);
|
|
3217
|
+
recordErrorContext(hardTimeoutError, {
|
|
3218
|
+
source: "deadline",
|
|
3219
|
+
stage: "initial_sync",
|
|
3220
|
+
originalCode: "initial_sync_timeout"
|
|
3221
|
+
});
|
|
3062
3222
|
hardController.abort(hardTimeoutError);
|
|
3063
3223
|
reject(hardTimeoutError);
|
|
3064
3224
|
}, hardTimeoutMs);
|
|
@@ -3107,7 +3267,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3107
3267
|
} catch (error) {
|
|
3108
3268
|
if (state.closed) return;
|
|
3109
3269
|
this.snapshotManager.dispose(state);
|
|
3110
|
-
state.lastError = toTransportError(error);
|
|
3270
|
+
state.lastError = toTransportError(error, "join");
|
|
3111
3271
|
this.logError("join first sync failed", error, { streamUrl: this.streamUrl });
|
|
3112
3272
|
state.readSubStatus = "error";
|
|
3113
3273
|
state.writeSubStatus = "error";
|
|
@@ -3155,7 +3315,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3155
3315
|
this.commitProducerAck(ack.producerAck);
|
|
3156
3316
|
didAppend = true;
|
|
3157
3317
|
}
|
|
3158
|
-
await
|
|
3318
|
+
await atErrorBoundary({
|
|
3319
|
+
source: "crdt",
|
|
3320
|
+
stage: "crdt_export"
|
|
3321
|
+
}, () => this.adapter.flushLocalExports?.());
|
|
3159
3322
|
const localBatch = this.exportUpdates(appliedVersion);
|
|
3160
3323
|
if (localBatch.batch != null) {
|
|
3161
3324
|
const appendedBatch = await this.appendLocalBatchRemote({
|
|
@@ -3176,7 +3339,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3176
3339
|
}
|
|
3177
3340
|
async syncOnce(operation, parentSignal) {
|
|
3178
3341
|
return this.enqueueExclusive(async () => {
|
|
3179
|
-
await
|
|
3342
|
+
await atErrorBoundary({
|
|
3343
|
+
source: "crdt",
|
|
3344
|
+
stage: "crdt_export"
|
|
3345
|
+
}, () => this.adapter.flushLocalExports?.());
|
|
3180
3346
|
return this.syncOnceExclusive(operation, parentSignal);
|
|
3181
3347
|
});
|
|
3182
3348
|
}
|
|
@@ -3240,11 +3406,17 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3240
3406
|
return createInitialRemoteCursor({
|
|
3241
3407
|
streamUrl: this.streamUrl,
|
|
3242
3408
|
nextOffset: "-1",
|
|
3243
|
-
serverLowerBoundVersion:
|
|
3409
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3410
|
+
source: "crdt",
|
|
3411
|
+
stage: "crdt_export"
|
|
3412
|
+
}, () => this.adapter.emptyVersion())
|
|
3244
3413
|
});
|
|
3245
3414
|
}
|
|
3246
3415
|
async resolveInitialRemoteState(operation, parentSignal) {
|
|
3247
|
-
const loaded = await
|
|
3416
|
+
const loaded = await atErrorBoundary({
|
|
3417
|
+
source: "cursor_store",
|
|
3418
|
+
stage: "cursor_load"
|
|
3419
|
+
}, () => this.remoteCursorStore.load(this.streamUrl));
|
|
3248
3420
|
const cursor = loaded ?? this.createInitialCursor();
|
|
3249
3421
|
const runInitial = (task) => this.runInitialSyncWithDeadline(operation, task, parentSignal);
|
|
3250
3422
|
try {
|
|
@@ -3269,7 +3441,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3269
3441
|
}
|
|
3270
3442
|
}
|
|
3271
3443
|
async resolvePullOnlyRemoteState(operation, parentSignal) {
|
|
3272
|
-
const loaded = await
|
|
3444
|
+
const loaded = await atErrorBoundary({
|
|
3445
|
+
source: "cursor_store",
|
|
3446
|
+
stage: "cursor_load"
|
|
3447
|
+
}, () => this.remoteCursorStore.load(this.streamUrl));
|
|
3273
3448
|
const cursor = loaded ?? this.createInitialCursor();
|
|
3274
3449
|
const runInitial = (task) => this.runInitialSyncWithDeadline(operation, task, parentSignal);
|
|
3275
3450
|
try {
|
|
@@ -3311,7 +3486,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3311
3486
|
}
|
|
3312
3487
|
async bootstrapState(cursor, options = {}) {
|
|
3313
3488
|
const cursorManager = options.cursorManager ?? this.cursorManager;
|
|
3314
|
-
const result = await this.client.bootstrap(options.signal, options.timeoutMode);
|
|
3489
|
+
const result = await atErrorBoundary({ stage: "bootstrap" }, () => this.client.bootstrap(options.signal, options.timeoutMode));
|
|
3315
3490
|
let saved = await cursorManager.applyBootstrapPayload(cursor, result.snapshot, result.updates, result.nextOffset, result.upToDate, result.snapshotOffset);
|
|
3316
3491
|
let bootstrapCursor = result.streamCursor;
|
|
3317
3492
|
if (!result.upToDate) {
|
|
@@ -3348,13 +3523,16 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3348
3523
|
const cursorManager = options.cursorManager ?? this.cursorManager;
|
|
3349
3524
|
while (true) {
|
|
3350
3525
|
const requestOffset = current.nextOffset;
|
|
3351
|
-
const response = await this.client.readFromOffset(requestOffset, currentStreamCursor, options.live, options.signal, options.timeoutMode);
|
|
3526
|
+
const response = await atErrorBoundary({ stage: "catch_up" }, () => this.client.readFromOffset(requestOffset, currentStreamCursor, options.live, options.signal, options.timeoutMode));
|
|
3352
3527
|
if (response.kind === "gone") {
|
|
3353
3528
|
if (goneStrategy === "return-gone") return StreamsCrdt.GONE_CATCHUP;
|
|
3354
3529
|
return await this.bootstrapState({
|
|
3355
3530
|
...current,
|
|
3356
3531
|
nextOffset: "-1",
|
|
3357
|
-
serverLowerBoundVersion:
|
|
3532
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3533
|
+
source: "crdt",
|
|
3534
|
+
stage: "crdt_export"
|
|
3535
|
+
}, () => this.adapter.emptyVersion())
|
|
3358
3536
|
}, {
|
|
3359
3537
|
cursorManager,
|
|
3360
3538
|
signal: options.signal,
|
|
@@ -3369,7 +3547,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3369
3547
|
if (error instanceof CrdtApplyIncompleteError && result.upToDate) return await this.bootstrapState({
|
|
3370
3548
|
...current,
|
|
3371
3549
|
nextOffset: "-1",
|
|
3372
|
-
serverLowerBoundVersion:
|
|
3550
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3551
|
+
source: "crdt",
|
|
3552
|
+
stage: "crdt_export"
|
|
3553
|
+
}, () => this.adapter.emptyVersion())
|
|
3373
3554
|
}, {
|
|
3374
3555
|
cursorManager,
|
|
3375
3556
|
signal: options.signal,
|
|
@@ -3390,7 +3571,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3390
3571
|
const bootstrapped = await this.bootstrapState({
|
|
3391
3572
|
...state.cursor,
|
|
3392
3573
|
nextOffset: "-1",
|
|
3393
|
-
serverLowerBoundVersion:
|
|
3574
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3575
|
+
source: "crdt",
|
|
3576
|
+
stage: "crdt_export"
|
|
3577
|
+
}, () => this.adapter.emptyVersion())
|
|
3394
3578
|
}, { signal: state.requestController?.signal });
|
|
3395
3579
|
state.cursor = bootstrapped.cursor;
|
|
3396
3580
|
state.streamCursor = bootstrapped.streamCursor;
|
|
@@ -3406,7 +3590,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3406
3590
|
streamUrl: this.streamUrl,
|
|
3407
3591
|
code: classified.code
|
|
3408
3592
|
});
|
|
3409
|
-
state.lastError = toTransportError(error);
|
|
3593
|
+
state.lastError = toTransportError(error, "live");
|
|
3410
3594
|
if (state.pendingLocal.length > 0) this.flushPendingLocal(state);
|
|
3411
3595
|
if (classified.retriable && !isAuthOrProtocolError(error)) {
|
|
3412
3596
|
state.incompleteRecoveryAttempt += 1;
|
|
@@ -3439,7 +3623,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3439
3623
|
localAppendReadCursor(frozen) {
|
|
3440
3624
|
return {
|
|
3441
3625
|
...frozen.baseCursor,
|
|
3442
|
-
serverLowerBoundVersion:
|
|
3626
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3627
|
+
source: "crdt",
|
|
3628
|
+
stage: "crdt_export"
|
|
3629
|
+
}, () => this.adapter.mergeVersions(frozen.baseCursor.serverLowerBoundVersion, frozen.batch.version))
|
|
3443
3630
|
};
|
|
3444
3631
|
}
|
|
3445
3632
|
async catchupLocalAppend(frozen, streamCursor) {
|
|
@@ -3471,7 +3658,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3471
3658
|
baseCursor: cursor,
|
|
3472
3659
|
batch,
|
|
3473
3660
|
pendingCount,
|
|
3474
|
-
wireUpdates: this.encodeUpdateItems == null ? batch.updates : await
|
|
3661
|
+
wireUpdates: this.encodeUpdateItems == null ? batch.updates : await atErrorBoundary({
|
|
3662
|
+
source: "local",
|
|
3663
|
+
stage: "payload_encode"
|
|
3664
|
+
}, this.encodeUpdateItems.bind(this, batch.updates)),
|
|
3475
3665
|
producerSession: this.createCurrentProducerSession()
|
|
3476
3666
|
};
|
|
3477
3667
|
this.frozenLocalAppend = frozen;
|
|
@@ -3482,7 +3672,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3482
3672
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
3483
3673
|
let result;
|
|
3484
3674
|
try {
|
|
3485
|
-
result = await this.client.appendUpdates(frozen.wireUpdates, frozen.producerSession);
|
|
3675
|
+
result = await atErrorBoundary({ stage: "upload" }, () => this.client.appendUpdates(frozen.wireUpdates, frozen.producerSession));
|
|
3486
3676
|
} catch (error) {
|
|
3487
3677
|
if (isStreamNotFoundError(error) && this.createStreamIfMissing) {
|
|
3488
3678
|
await this.ensureStreamExists();
|
|
@@ -3495,7 +3685,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3495
3685
|
cursor: {
|
|
3496
3686
|
...frozen.baseCursor,
|
|
3497
3687
|
nextOffset: result.nextOffset,
|
|
3498
|
-
serverLowerBoundVersion:
|
|
3688
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3689
|
+
source: "crdt",
|
|
3690
|
+
stage: "crdt_export"
|
|
3691
|
+
}, () => this.adapter.mergeVersions(frozen.baseCursor.serverLowerBoundVersion, frozen.batch.version))
|
|
3499
3692
|
},
|
|
3500
3693
|
producerAck: {
|
|
3501
3694
|
epoch: result.ackEpoch,
|
|
@@ -3570,9 +3763,15 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3570
3763
|
}
|
|
3571
3764
|
}
|
|
3572
3765
|
exportUpdates(fromVersion) {
|
|
3573
|
-
const exported =
|
|
3766
|
+
const exported = atSyncErrorBoundary({
|
|
3767
|
+
source: "crdt",
|
|
3768
|
+
stage: "crdt_export"
|
|
3769
|
+
}, () => this.adapter.exportUpdates(fromVersion));
|
|
3574
3770
|
if (exported == null) return { nextRefVersion: fromVersion };
|
|
3575
|
-
const nextRefVersion =
|
|
3771
|
+
const nextRefVersion = atSyncErrorBoundary({
|
|
3772
|
+
source: "crdt",
|
|
3773
|
+
stage: "crdt_export"
|
|
3774
|
+
}, () => this.adapter.mergeVersions(fromVersion, exported.version));
|
|
3576
3775
|
if (exported.updates.length === 0) return { nextRefVersion };
|
|
3577
3776
|
return {
|
|
3578
3777
|
batch: exported,
|
|
@@ -3629,10 +3828,16 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3629
3828
|
const bootstrapCursor = {
|
|
3630
3829
|
...cursor,
|
|
3631
3830
|
nextOffset: "-1",
|
|
3632
|
-
serverLowerBoundVersion:
|
|
3831
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3832
|
+
source: "crdt",
|
|
3833
|
+
stage: "crdt_export"
|
|
3834
|
+
}, () => this.adapter.emptyVersion())
|
|
3633
3835
|
};
|
|
3634
3836
|
if (isolatedCursorManager != null) return await this.inferRemoteAndAppendLocal(bootstrapCursor, isolatedCursorManager, operation, parentSignal);
|
|
3635
|
-
const preservedLocalSnapshot =
|
|
3837
|
+
const preservedLocalSnapshot = atSyncErrorBoundary({
|
|
3838
|
+
source: "crdt",
|
|
3839
|
+
stage: "crdt_export"
|
|
3840
|
+
}, () => this.adapter.exportSnapshot());
|
|
3636
3841
|
let restoredLocalSnapshot = false;
|
|
3637
3842
|
try {
|
|
3638
3843
|
const inferredRemote = await this.runInitialSyncWithDeadline(operation, (signal) => this.bootstrapState(bootstrapCursor, {
|
|
@@ -3640,7 +3845,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3640
3845
|
signal,
|
|
3641
3846
|
timeoutMode: "initial"
|
|
3642
3847
|
}), parentSignal);
|
|
3643
|
-
await
|
|
3848
|
+
await atErrorBoundary({
|
|
3849
|
+
source: "crdt",
|
|
3850
|
+
stage: "crdt_apply"
|
|
3851
|
+
}, async () => this.adapter.applySnapshot(preservedLocalSnapshot));
|
|
3644
3852
|
restoredLocalSnapshot = true;
|
|
3645
3853
|
let pendingAppend;
|
|
3646
3854
|
if (this.frozenLocalAppend != null) {
|
|
@@ -3657,7 +3865,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3657
3865
|
if (pendingAppend != null) this.commitProducerAck(pendingAppend.producerAck);
|
|
3658
3866
|
return result;
|
|
3659
3867
|
} catch (error) {
|
|
3660
|
-
if (!restoredLocalSnapshot) await
|
|
3868
|
+
if (!restoredLocalSnapshot) await atErrorBoundary({
|
|
3869
|
+
source: "crdt",
|
|
3870
|
+
stage: "crdt_apply"
|
|
3871
|
+
}, async () => this.adapter.applySnapshot(preservedLocalSnapshot));
|
|
3661
3872
|
throw error;
|
|
3662
3873
|
}
|
|
3663
3874
|
}
|
|
@@ -3744,7 +3955,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3744
3955
|
streamUrl: this.streamUrl,
|
|
3745
3956
|
attempts: state.retryAttempt
|
|
3746
3957
|
});
|
|
3747
|
-
state.lastError = toTransportError(error);
|
|
3958
|
+
state.lastError = toTransportError(error, "live");
|
|
3748
3959
|
this.setReadSubStatus(state, "disconnected");
|
|
3749
3960
|
return false;
|
|
3750
3961
|
}
|
|
@@ -3777,12 +3988,15 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3777
3988
|
try {
|
|
3778
3989
|
if (state.liveMode === "long-poll") {
|
|
3779
3990
|
const requestOffset = state.cursor.nextOffset;
|
|
3780
|
-
const response = await this.client.readFromOffset(requestOffset, state.streamCursor, "long-poll", capturedController?.signal);
|
|
3991
|
+
const response = await atErrorBoundary({ stage: "catch_up" }, () => this.client.readFromOffset(requestOffset, state.streamCursor, "long-poll", capturedController?.signal));
|
|
3781
3992
|
if (response.kind === "gone") {
|
|
3782
3993
|
const bootstrapped = await this.bootstrapState({
|
|
3783
3994
|
...state.cursor,
|
|
3784
3995
|
nextOffset: "-1",
|
|
3785
|
-
serverLowerBoundVersion:
|
|
3996
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
3997
|
+
source: "crdt",
|
|
3998
|
+
stage: "crdt_export"
|
|
3999
|
+
}, () => this.adapter.emptyVersion())
|
|
3786
4000
|
}, { signal: capturedController?.signal });
|
|
3787
4001
|
state.cursor = bootstrapped.cursor;
|
|
3788
4002
|
state.streamCursor = bootstrapped.streamCursor;
|
|
@@ -3869,14 +4083,17 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3869
4083
|
streamUrl: this.streamUrl,
|
|
3870
4084
|
code: "stream_not_found"
|
|
3871
4085
|
});
|
|
3872
|
-
state.lastError = toTransportError(notFoundError);
|
|
4086
|
+
state.lastError = toTransportError(notFoundError, "live");
|
|
3873
4087
|
this.setReadSubStatus(state, "error");
|
|
3874
4088
|
return;
|
|
3875
4089
|
}
|
|
3876
4090
|
const bootstrapped = await this.bootstrapState({
|
|
3877
4091
|
...state.cursor,
|
|
3878
4092
|
nextOffset: "-1",
|
|
3879
|
-
serverLowerBoundVersion:
|
|
4093
|
+
serverLowerBoundVersion: atSyncErrorBoundary({
|
|
4094
|
+
source: "crdt",
|
|
4095
|
+
stage: "crdt_export"
|
|
4096
|
+
}, () => this.adapter.emptyVersion())
|
|
3880
4097
|
}, { signal: capturedController?.signal });
|
|
3881
4098
|
state.cursor = bootstrapped.cursor;
|
|
3882
4099
|
state.streamCursor = bootstrapped.streamCursor;
|
|
@@ -3933,7 +4150,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3933
4150
|
streamUrl: this.streamUrl,
|
|
3934
4151
|
code: flushClassified.code
|
|
3935
4152
|
});
|
|
3936
|
-
state.lastError = toTransportError(flushError);
|
|
4153
|
+
state.lastError = toTransportError(flushError, "live");
|
|
3937
4154
|
this.setReadSubStatus(state, "error");
|
|
3938
4155
|
return;
|
|
3939
4156
|
}
|
|
@@ -3948,7 +4165,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3948
4165
|
streamUrl: this.streamUrl,
|
|
3949
4166
|
code: classified.code
|
|
3950
4167
|
});
|
|
3951
|
-
state.lastError = toTransportError(error);
|
|
4168
|
+
state.lastError = toTransportError(error, "live");
|
|
3952
4169
|
this.setReadSubStatus(state, "error");
|
|
3953
4170
|
return;
|
|
3954
4171
|
}
|
|
@@ -3981,7 +4198,10 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
3981
4198
|
const candidateUpdates = [...allUpdates, ...next.updates];
|
|
3982
4199
|
if (await this.measureAppendBodyByteLength(candidateUpdates) > maxBytes) break;
|
|
3983
4200
|
allUpdates.push(...next.updates);
|
|
3984
|
-
mergedVersion =
|
|
4201
|
+
mergedVersion = atSyncErrorBoundary({
|
|
4202
|
+
source: "crdt",
|
|
4203
|
+
stage: "crdt_export"
|
|
4204
|
+
}, () => this.adapter.mergeVersions(mergedVersion, next.version));
|
|
3985
4205
|
count += 1;
|
|
3986
4206
|
}
|
|
3987
4207
|
if (count === 1) return {
|
|
@@ -4078,7 +4298,7 @@ var StreamsCrdt = class StreamsCrdt {
|
|
|
4078
4298
|
break;
|
|
4079
4299
|
} catch (error) {
|
|
4080
4300
|
const classified = classifyFetchError(error);
|
|
4081
|
-
const transportError = toTransportError(error);
|
|
4301
|
+
const transportError = toTransportError(error, "upload");
|
|
4082
4302
|
if (!classified.retriable || isAuthOrProtocolError(error)) {
|
|
4083
4303
|
if (isPayloadTooLargeError(error)) state.flushHeadBatchOnly = true;
|
|
4084
4304
|
this.logError("local append failed", error, {
|
|
@@ -4255,4 +4475,4 @@ function isValidRillId(id) {
|
|
|
4255
4475
|
//#endregion
|
|
4256
4476
|
export { createInitialRemoteCursor as a, PayloadProtectionError as c, IndexedDbRemoteCursorStore as i, StreamsCrdt as n, EphemeralStreamCrdt as o, InMemoryRemoteCursorStore as r, LocalAppendFailedError as s, isValidRillId as t };
|
|
4257
4477
|
|
|
4258
|
-
//# sourceMappingURL=stream-id-
|
|
4478
|
+
//# sourceMappingURL=stream-id-Dlnc1PNH.js.map
|