@electric-sql/client 1.5.6 → 1.5.8
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/cjs/index.cjs +131 -15
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +4 -2
- package/dist/index.browser.mjs +8 -4
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.legacy-esm.js +131 -15
- package/dist/index.legacy-esm.js.map +1 -1
- package/dist/index.mjs +131 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +149 -9
- package/src/expired-shapes-cache.ts +5 -0
- package/src/fetch.ts +3 -3
- package/src/helpers.ts +16 -1
- package/src/shape-stream-state.ts +10 -0
- package/src/shape.ts +6 -2
- package/src/types.ts +1 -1
- package/src/up-to-date-tracker.ts +5 -0
package/dist/index.d.ts
CHANGED
|
@@ -73,7 +73,7 @@ type SubsetParams = {
|
|
|
73
73
|
/** Legacy string format WHERE clause */
|
|
74
74
|
where?: string;
|
|
75
75
|
/** Positional parameter values for WHERE clause */
|
|
76
|
-
params?: Record<string, string>;
|
|
76
|
+
params?: Record<string, string | bigint | number>;
|
|
77
77
|
/** Maximum number of rows to return */
|
|
78
78
|
limit?: number;
|
|
79
79
|
/** Number of rows to skip */
|
|
@@ -783,11 +783,13 @@ declare class ShapeStream<T extends Row<unknown> = Row> implements ShapeStreamIn
|
|
|
783
783
|
* `subsetMethod: 'POST'` on the stream to send parameters in the request body instead.
|
|
784
784
|
*
|
|
785
785
|
* @param opts - The options for the snapshot request.
|
|
786
|
-
* @returns The metadata and the
|
|
786
|
+
* @returns The metadata, data, and the response's offset/handle for state advancement.
|
|
787
787
|
*/
|
|
788
788
|
fetchSnapshot(opts: SubsetParams): Promise<{
|
|
789
789
|
metadata: SnapshotMetadata;
|
|
790
790
|
data: Array<ChangeMessage<T>>;
|
|
791
|
+
responseOffset: Offset | null;
|
|
792
|
+
responseHandle: string | null;
|
|
791
793
|
}>;
|
|
792
794
|
}
|
|
793
795
|
|
package/dist/index.legacy-esm.js
CHANGED
|
@@ -429,7 +429,7 @@ function isChangeMessage(message) {
|
|
|
429
429
|
return message != null && `key` in message;
|
|
430
430
|
}
|
|
431
431
|
function isControlMessage(message) {
|
|
432
|
-
return message != null &&
|
|
432
|
+
return message != null && `headers` in message && `control` in message.headers;
|
|
433
433
|
}
|
|
434
434
|
function isUpToDateMessage(message) {
|
|
435
435
|
return isControlMessage(message) && message.headers.control === `up-to-date`;
|
|
@@ -439,6 +439,12 @@ function getOffset(message) {
|
|
|
439
439
|
const lsn = message.headers.global_last_seen_lsn;
|
|
440
440
|
return lsn ? `${lsn}_0` : void 0;
|
|
441
441
|
}
|
|
442
|
+
function bigintReplacer(_key, value) {
|
|
443
|
+
return typeof value === `bigint` ? value.toString() : value;
|
|
444
|
+
}
|
|
445
|
+
function bigintSafeStringify(value) {
|
|
446
|
+
return JSON.stringify(value, bigintReplacer);
|
|
447
|
+
}
|
|
442
448
|
function isVisibleInSnapshot(txid, snapshot) {
|
|
443
449
|
const xid = BigInt(txid);
|
|
444
450
|
const xmin = BigInt(snapshot.xmin);
|
|
@@ -498,10 +504,9 @@ var ELECTRIC_PROTOCOL_QUERY_PARAMS = [
|
|
|
498
504
|
// src/fetch.ts
|
|
499
505
|
var HTTP_RETRY_STATUS_CODES = [429];
|
|
500
506
|
var BackoffDefaults = {
|
|
501
|
-
initialDelay:
|
|
502
|
-
maxDelay:
|
|
503
|
-
|
|
504
|
-
multiplier: 1.3,
|
|
507
|
+
initialDelay: 1e3,
|
|
508
|
+
maxDelay: 32e3,
|
|
509
|
+
multiplier: 2,
|
|
505
510
|
maxRetries: Infinity
|
|
506
511
|
// Retry forever - clients may go offline and come back
|
|
507
512
|
};
|
|
@@ -1116,6 +1121,10 @@ var ExpiredShapesCache = class {
|
|
|
1116
1121
|
this.data = {};
|
|
1117
1122
|
this.save();
|
|
1118
1123
|
}
|
|
1124
|
+
delete(shapeUrl) {
|
|
1125
|
+
delete this.data[shapeUrl];
|
|
1126
|
+
this.save();
|
|
1127
|
+
}
|
|
1119
1128
|
};
|
|
1120
1129
|
var expiredShapesCache = new ExpiredShapesCache();
|
|
1121
1130
|
|
|
@@ -1237,6 +1246,10 @@ var UpToDateTracker = class {
|
|
|
1237
1246
|
}
|
|
1238
1247
|
this.save();
|
|
1239
1248
|
}
|
|
1249
|
+
delete(shapeKey) {
|
|
1250
|
+
delete this.data[shapeKey];
|
|
1251
|
+
this.save();
|
|
1252
|
+
}
|
|
1240
1253
|
};
|
|
1241
1254
|
var upToDateTracker = new UpToDateTracker();
|
|
1242
1255
|
|
|
@@ -1704,6 +1717,13 @@ var PausedState = class _PausedState extends ShapeStreamState {
|
|
|
1704
1717
|
get replayCursor() {
|
|
1705
1718
|
return this.previousState.replayCursor;
|
|
1706
1719
|
}
|
|
1720
|
+
handleResponseMetadata(input) {
|
|
1721
|
+
const transition = this.previousState.handleResponseMetadata(input);
|
|
1722
|
+
if (transition.action === `accepted`) {
|
|
1723
|
+
return { action: `accepted`, state: new _PausedState(transition.state) };
|
|
1724
|
+
}
|
|
1725
|
+
return transition;
|
|
1726
|
+
}
|
|
1707
1727
|
withHandle(handle) {
|
|
1708
1728
|
return new _PausedState(this.previousState.withHandle(handle));
|
|
1709
1729
|
}
|
|
@@ -1854,6 +1874,7 @@ var RESERVED_PARAMS = /* @__PURE__ */ new Set([
|
|
|
1854
1874
|
OFFSET_QUERY_PARAM,
|
|
1855
1875
|
CACHE_BUSTER_QUERY_PARAM
|
|
1856
1876
|
]);
|
|
1877
|
+
var TROUBLESHOOTING_URL = `https://electric-sql.com/docs/guides/troubleshooting`;
|
|
1857
1878
|
async function resolveValue(value) {
|
|
1858
1879
|
if (typeof value === `function`) {
|
|
1859
1880
|
return value();
|
|
@@ -1894,7 +1915,7 @@ function canonicalShapeKey(url) {
|
|
|
1894
1915
|
cleanUrl.searchParams.sort();
|
|
1895
1916
|
return cleanUrl.toString();
|
|
1896
1917
|
}
|
|
1897
|
-
var _error, _fetchClient2, _sseFetchClient, _messageParser, _subscribers, _started, _syncState, _connected, _mode, _onError, _requestAbortController, _refreshCount, _snapshotCounter, _ShapeStream_instances, isRefreshing_get, _tickPromise, _tickPromiseResolver, _tickPromiseRejecter, _messageChain, _snapshotTracker, _pauseLock, _currentFetchUrl, _lastSseConnectionStartTime, _minSseConnectionDuration, _maxShortSseConnections, _sseBackoffBaseDelay, _sseBackoffMaxDelay, _unsubscribeFromVisibilityChanges, _unsubscribeFromWakeDetection, _maxStaleCacheRetries, start_fn, teardown_fn, requestShape_fn, constructUrl_fn, createAbortListener_fn, onInitialResponse_fn, onMessages_fn, fetchShape_fn, requestShapeLongPoll_fn, requestShapeSSE_fn, nextTick_fn, publish_fn, sendErrorToSubscribers_fn, hasBrowserVisibilityAPI_fn, subscribeToVisibilityChanges_fn, subscribeToWakeDetection_fn, reset_fn, buildSubsetBody_fn;
|
|
1918
|
+
var _error, _fetchClient2, _sseFetchClient, _messageParser, _subscribers, _started, _syncState, _connected, _mode, _onError, _requestAbortController, _refreshCount, _snapshotCounter, _ShapeStream_instances, isRefreshing_get, _tickPromise, _tickPromiseResolver, _tickPromiseRejecter, _messageChain, _snapshotTracker, _pauseLock, _currentFetchUrl, _lastSseConnectionStartTime, _minSseConnectionDuration, _maxShortSseConnections, _sseBackoffBaseDelay, _sseBackoffMaxDelay, _unsubscribeFromVisibilityChanges, _unsubscribeFromWakeDetection, _maxStaleCacheRetries, _recentRequestEntries, _fastLoopWindowMs, _fastLoopThreshold, _fastLoopBackoffBaseMs, _fastLoopBackoffMaxMs, _fastLoopConsecutiveCount, _fastLoopMaxCount, start_fn, teardown_fn, requestShape_fn, checkFastLoop_fn, constructUrl_fn, createAbortListener_fn, onInitialResponse_fn, onMessages_fn, fetchShape_fn, requestShapeLongPoll_fn, requestShapeSSE_fn, nextTick_fn, publish_fn, sendErrorToSubscribers_fn, hasBrowserVisibilityAPI_fn, subscribeToVisibilityChanges_fn, subscribeToWakeDetection_fn, reset_fn, buildSubsetBody_fn;
|
|
1898
1919
|
var ShapeStream = class {
|
|
1899
1920
|
constructor(options) {
|
|
1900
1921
|
__privateAdd(this, _ShapeStream_instances);
|
|
@@ -1932,6 +1953,15 @@ var ShapeStream = class {
|
|
|
1932
1953
|
__privateAdd(this, _unsubscribeFromVisibilityChanges);
|
|
1933
1954
|
__privateAdd(this, _unsubscribeFromWakeDetection);
|
|
1934
1955
|
__privateAdd(this, _maxStaleCacheRetries, 3);
|
|
1956
|
+
// Fast-loop detection: track recent non-live requests to detect tight retry
|
|
1957
|
+
// loops caused by proxy/CDN misconfiguration or stale client-side caches
|
|
1958
|
+
__privateAdd(this, _recentRequestEntries, []);
|
|
1959
|
+
__privateAdd(this, _fastLoopWindowMs, 500);
|
|
1960
|
+
__privateAdd(this, _fastLoopThreshold, 5);
|
|
1961
|
+
__privateAdd(this, _fastLoopBackoffBaseMs, 100);
|
|
1962
|
+
__privateAdd(this, _fastLoopBackoffMaxMs, 5e3);
|
|
1963
|
+
__privateAdd(this, _fastLoopConsecutiveCount, 0);
|
|
1964
|
+
__privateAdd(this, _fastLoopMaxCount, 5);
|
|
1935
1965
|
var _a, _b, _c, _d;
|
|
1936
1966
|
this.options = __spreadValues({ subscribe: true }, options);
|
|
1937
1967
|
validateOptions(this.options);
|
|
@@ -2094,7 +2124,7 @@ var ShapeStream = class {
|
|
|
2094
2124
|
);
|
|
2095
2125
|
}, 3e4);
|
|
2096
2126
|
try {
|
|
2097
|
-
const { metadata, data } = await this.fetchSnapshot(opts);
|
|
2127
|
+
const { metadata, data, responseOffset, responseHandle } = await this.fetchSnapshot(opts);
|
|
2098
2128
|
const dataWithEndBoundary = data.concat([
|
|
2099
2129
|
{ headers: __spreadValues({ control: `snapshot-end` }, metadata) },
|
|
2100
2130
|
{ headers: __spreadValues({ control: `subset-end` }, opts) }
|
|
@@ -2104,6 +2134,25 @@ var ShapeStream = class {
|
|
|
2104
2134
|
new Set(data.map((message) => message.key))
|
|
2105
2135
|
);
|
|
2106
2136
|
__privateMethod(this, _ShapeStream_instances, onMessages_fn).call(this, dataWithEndBoundary, false);
|
|
2137
|
+
if (responseOffset !== null || responseHandle !== null) {
|
|
2138
|
+
const transition = __privateGet(this, _syncState).handleResponseMetadata({
|
|
2139
|
+
status: 200,
|
|
2140
|
+
responseHandle,
|
|
2141
|
+
responseOffset,
|
|
2142
|
+
responseCursor: null,
|
|
2143
|
+
expiredHandle: null,
|
|
2144
|
+
now: Date.now(),
|
|
2145
|
+
maxStaleCacheRetries: __privateGet(this, _maxStaleCacheRetries),
|
|
2146
|
+
createCacheBuster: () => `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`
|
|
2147
|
+
});
|
|
2148
|
+
if (transition.action === `accepted`) {
|
|
2149
|
+
__privateSet(this, _syncState, transition.state);
|
|
2150
|
+
} else {
|
|
2151
|
+
console.warn(
|
|
2152
|
+
`[Electric] Snapshot response metadata was not accepted by state "${__privateGet(this, _syncState).kind}" (action: ${transition.action}). Stream offset was not advanced from snapshot.`
|
|
2153
|
+
);
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2107
2156
|
return {
|
|
2108
2157
|
metadata,
|
|
2109
2158
|
data
|
|
@@ -2122,7 +2171,7 @@ var ShapeStream = class {
|
|
|
2122
2171
|
* `subsetMethod: 'POST'` on the stream to send parameters in the request body instead.
|
|
2123
2172
|
*
|
|
2124
2173
|
* @param opts - The options for the snapshot request.
|
|
2125
|
-
* @returns The metadata and the
|
|
2174
|
+
* @returns The metadata, data, and the response's offset/handle for state advancement.
|
|
2126
2175
|
*/
|
|
2127
2176
|
async fetchSnapshot(opts) {
|
|
2128
2177
|
var _a, _b, _c;
|
|
@@ -2138,7 +2187,7 @@ var ShapeStream = class {
|
|
|
2138
2187
|
headers: __spreadProps(__spreadValues({}, result.requestHeaders), {
|
|
2139
2188
|
"Content-Type": `application/json`
|
|
2140
2189
|
}),
|
|
2141
|
-
body:
|
|
2190
|
+
body: bigintSafeStringify(__privateMethod(this, _ShapeStream_instances, buildSubsetBody_fn).call(this, opts))
|
|
2142
2191
|
};
|
|
2143
2192
|
} else {
|
|
2144
2193
|
const result = await __privateMethod(this, _ShapeStream_instances, constructUrl_fn).call(this, this.options.url, true, opts);
|
|
@@ -2173,7 +2222,9 @@ var ShapeStream = class {
|
|
|
2173
2222
|
rawData,
|
|
2174
2223
|
schema
|
|
2175
2224
|
);
|
|
2176
|
-
|
|
2225
|
+
const responseOffset = response.headers.get(CHUNK_LAST_OFFSET_HEADER) || null;
|
|
2226
|
+
const responseHandle = response.headers.get(SHAPE_HANDLE_HEADER);
|
|
2227
|
+
return { metadata, data, responseOffset, responseHandle };
|
|
2177
2228
|
}
|
|
2178
2229
|
};
|
|
2179
2230
|
_error = new WeakMap();
|
|
@@ -2208,6 +2259,13 @@ _sseBackoffMaxDelay = new WeakMap();
|
|
|
2208
2259
|
_unsubscribeFromVisibilityChanges = new WeakMap();
|
|
2209
2260
|
_unsubscribeFromWakeDetection = new WeakMap();
|
|
2210
2261
|
_maxStaleCacheRetries = new WeakMap();
|
|
2262
|
+
_recentRequestEntries = new WeakMap();
|
|
2263
|
+
_fastLoopWindowMs = new WeakMap();
|
|
2264
|
+
_fastLoopThreshold = new WeakMap();
|
|
2265
|
+
_fastLoopBackoffBaseMs = new WeakMap();
|
|
2266
|
+
_fastLoopBackoffMaxMs = new WeakMap();
|
|
2267
|
+
_fastLoopConsecutiveCount = new WeakMap();
|
|
2268
|
+
_fastLoopMaxCount = new WeakMap();
|
|
2211
2269
|
start_fn = async function() {
|
|
2212
2270
|
var _a, _b;
|
|
2213
2271
|
__privateSet(this, _started, true);
|
|
@@ -2232,6 +2290,8 @@ start_fn = async function() {
|
|
|
2232
2290
|
if (__privateGet(this, _syncState) instanceof ErrorState) {
|
|
2233
2291
|
__privateSet(this, _syncState, __privateGet(this, _syncState).retry());
|
|
2234
2292
|
}
|
|
2293
|
+
__privateSet(this, _fastLoopConsecutiveCount, 0);
|
|
2294
|
+
__privateSet(this, _recentRequestEntries, []);
|
|
2235
2295
|
__privateSet(this, _started, false);
|
|
2236
2296
|
await __privateMethod(this, _ShapeStream_instances, start_fn).call(this);
|
|
2237
2297
|
return;
|
|
@@ -2262,6 +2322,12 @@ requestShape_fn = async function() {
|
|
|
2262
2322
|
if (!this.options.subscribe && (((_a = this.options.signal) == null ? void 0 : _a.aborted) || __privateGet(this, _syncState).isUpToDate)) {
|
|
2263
2323
|
return;
|
|
2264
2324
|
}
|
|
2325
|
+
if (!__privateGet(this, _syncState).isUpToDate) {
|
|
2326
|
+
await __privateMethod(this, _ShapeStream_instances, checkFastLoop_fn).call(this);
|
|
2327
|
+
} else {
|
|
2328
|
+
__privateSet(this, _fastLoopConsecutiveCount, 0);
|
|
2329
|
+
__privateSet(this, _recentRequestEntries, []);
|
|
2330
|
+
}
|
|
2265
2331
|
let resumingFromPause = false;
|
|
2266
2332
|
if (__privateGet(this, _syncState) instanceof PausedState) {
|
|
2267
2333
|
resumingFromPause = true;
|
|
@@ -2320,6 +2386,56 @@ requestShape_fn = async function() {
|
|
|
2320
2386
|
(_b = __privateGet(this, _tickPromiseResolver)) == null ? void 0 : _b.call(this);
|
|
2321
2387
|
return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
|
|
2322
2388
|
};
|
|
2389
|
+
checkFastLoop_fn = async function() {
|
|
2390
|
+
const now = Date.now();
|
|
2391
|
+
const currentOffset = __privateGet(this, _syncState).offset;
|
|
2392
|
+
__privateSet(this, _recentRequestEntries, __privateGet(this, _recentRequestEntries).filter(
|
|
2393
|
+
(e) => now - e.timestamp < __privateGet(this, _fastLoopWindowMs)
|
|
2394
|
+
));
|
|
2395
|
+
__privateGet(this, _recentRequestEntries).push({ timestamp: now, offset: currentOffset });
|
|
2396
|
+
const sameOffsetCount = __privateGet(this, _recentRequestEntries).filter(
|
|
2397
|
+
(e) => e.offset === currentOffset
|
|
2398
|
+
).length;
|
|
2399
|
+
if (sameOffsetCount < __privateGet(this, _fastLoopThreshold)) return;
|
|
2400
|
+
__privateWrapper(this, _fastLoopConsecutiveCount)._++;
|
|
2401
|
+
if (__privateGet(this, _fastLoopConsecutiveCount) >= __privateGet(this, _fastLoopMaxCount)) {
|
|
2402
|
+
throw new FetchError(
|
|
2403
|
+
502,
|
|
2404
|
+
void 0,
|
|
2405
|
+
void 0,
|
|
2406
|
+
{},
|
|
2407
|
+
this.options.url,
|
|
2408
|
+
`Client is stuck in a fast retry loop (${__privateGet(this, _fastLoopThreshold)} requests in ${__privateGet(this, _fastLoopWindowMs)}ms at the same offset, repeated ${__privateGet(this, _fastLoopMaxCount)} times). Client-side caches were cleared automatically on first detection, but the loop persists. This usually indicates a proxy or CDN misconfiguration. Common causes:
|
|
2409
|
+
- Proxy is not including query parameters (handle, offset) in its cache key
|
|
2410
|
+
- CDN is serving stale 409 responses
|
|
2411
|
+
- Proxy is stripping required Electric headers from responses
|
|
2412
|
+
For more information visit the troubleshooting guide: ${TROUBLESHOOTING_URL}`
|
|
2413
|
+
);
|
|
2414
|
+
}
|
|
2415
|
+
if (__privateGet(this, _fastLoopConsecutiveCount) === 1) {
|
|
2416
|
+
console.warn(
|
|
2417
|
+
`[Electric] Detected fast retry loop (${__privateGet(this, _fastLoopThreshold)} requests in ${__privateGet(this, _fastLoopWindowMs)}ms at the same offset). Clearing client-side caches and resetting stream to recover. If this persists, check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key, and that required Electric headers are forwarded to the client. For more information visit the troubleshooting guide: ${TROUBLESHOOTING_URL}`
|
|
2418
|
+
);
|
|
2419
|
+
if (__privateGet(this, _currentFetchUrl)) {
|
|
2420
|
+
const shapeKey = canonicalShapeKey(__privateGet(this, _currentFetchUrl));
|
|
2421
|
+
expiredShapesCache.delete(shapeKey);
|
|
2422
|
+
upToDateTracker.delete(shapeKey);
|
|
2423
|
+
} else {
|
|
2424
|
+
expiredShapesCache.clear();
|
|
2425
|
+
upToDateTracker.clear();
|
|
2426
|
+
}
|
|
2427
|
+
__privateMethod(this, _ShapeStream_instances, reset_fn).call(this);
|
|
2428
|
+
__privateSet(this, _recentRequestEntries, []);
|
|
2429
|
+
return;
|
|
2430
|
+
}
|
|
2431
|
+
const maxDelay = Math.min(
|
|
2432
|
+
__privateGet(this, _fastLoopBackoffMaxMs),
|
|
2433
|
+
__privateGet(this, _fastLoopBackoffBaseMs) * Math.pow(2, __privateGet(this, _fastLoopConsecutiveCount))
|
|
2434
|
+
);
|
|
2435
|
+
const delayMs = Math.floor(Math.random() * maxDelay);
|
|
2436
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
2437
|
+
__privateSet(this, _recentRequestEntries, []);
|
|
2438
|
+
};
|
|
2323
2439
|
constructUrl_fn = async function(url, resumingFromPause, subsetParams) {
|
|
2324
2440
|
var _a, _b, _c, _d, _e, _f;
|
|
2325
2441
|
const [requestHeaders, params] = await Promise.all([
|
|
@@ -2386,7 +2502,7 @@ constructUrl_fn = async function(url, resumingFromPause, subsetParams) {
|
|
|
2386
2502
|
if (subsetParams.params)
|
|
2387
2503
|
fetchUrl.searchParams.set(
|
|
2388
2504
|
SUBSET_PARAM_WHERE_PARAMS,
|
|
2389
|
-
|
|
2505
|
+
bigintSafeStringify(subsetParams.params)
|
|
2390
2506
|
);
|
|
2391
2507
|
if (subsetParams.limit)
|
|
2392
2508
|
setQueryParam(fetchUrl, SUBSET_PARAM_LIMIT, subsetParams.limit);
|
|
@@ -2470,11 +2586,11 @@ onInitialResponse_fn = async function(response) {
|
|
|
2470
2586
|
void 0,
|
|
2471
2587
|
{},
|
|
2472
2588
|
(_c = (_b = __privateGet(this, _currentFetchUrl)) == null ? void 0 : _b.toString()) != null ? _c : ``,
|
|
2473
|
-
`CDN continues serving stale cached responses after ${__privateGet(this, _maxStaleCacheRetries)} retry attempts. This indicates a severe proxy/CDN misconfiguration. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. For more information visit the troubleshooting guide:
|
|
2589
|
+
`CDN continues serving stale cached responses after ${__privateGet(this, _maxStaleCacheRetries)} retry attempts. This indicates a severe proxy/CDN misconfiguration. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. For more information visit the troubleshooting guide: ${TROUBLESHOOTING_URL}`
|
|
2474
2590
|
);
|
|
2475
2591
|
}
|
|
2476
2592
|
console.warn(
|
|
2477
|
-
`[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${shapeHandle}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. For more information visit the troubleshooting guide:
|
|
2593
|
+
`[Electric] Received stale cached response with expired shape handle. This should not happen and indicates a proxy/CDN caching misconfiguration. The response contained handle "${shapeHandle}" which was previously marked as expired. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key. For more information visit the troubleshooting guide: ${TROUBLESHOOTING_URL} Retrying with a random cache buster to bypass the stale cache (attempt ${__privateGet(this, _syncState).staleCacheRetryCount}/${__privateGet(this, _maxStaleCacheRetries)}).`
|
|
2478
2594
|
);
|
|
2479
2595
|
throw new StaleCacheError(
|
|
2480
2596
|
`Received stale cached response with expired handle "${shapeHandle}". This indicates a proxy/CDN caching misconfiguration. Check that your proxy includes all query parameters (especially 'handle' and 'offset') in its cache key.`
|
|
@@ -2565,7 +2681,7 @@ requestShapeLongPoll_fn = async function(opts) {
|
|
|
2565
2681
|
const messages = res || `[]`;
|
|
2566
2682
|
const batch = __privateGet(this, _messageParser).parse(messages, schema);
|
|
2567
2683
|
if (!Array.isArray(batch)) {
|
|
2568
|
-
const preview = (_a =
|
|
2684
|
+
const preview = (_a = bigintSafeStringify(batch)) == null ? void 0 : _a.slice(0, 200);
|
|
2569
2685
|
throw new FetchError(
|
|
2570
2686
|
response.status,
|
|
2571
2687
|
`Received non-array response body from shape endpoint. This may indicate a proxy or CDN is returning an unexpected response. Expected a JSON array, got ${typeof batch}: ${preview}`,
|
|
@@ -2929,7 +3045,7 @@ var Shape = class {
|
|
|
2929
3045
|
* Returns void; data will be emitted via the stream and processed by this Shape.
|
|
2930
3046
|
*/
|
|
2931
3047
|
async requestSnapshot(params) {
|
|
2932
|
-
const key =
|
|
3048
|
+
const key = bigintSafeStringify(params);
|
|
2933
3049
|
__privateGet(this, _requestedSubSnapshots).add(key);
|
|
2934
3050
|
await __privateMethod(this, _Shape_instances, awaitUpToDate_fn).call(this);
|
|
2935
3051
|
await this.stream.requestSnapshot(params);
|