cry-synced-db-client 0.1.210 → 0.1.213
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Versions
|
|
2
2
|
|
|
3
|
+
## 0.1.211 (2026-06-25)
|
|
4
|
+
|
|
5
|
+
### Added `streamActivityTimeoutMs` to SyncedDbConfig
|
|
6
|
+
|
|
7
|
+
`findNewerManyStream` has two internal timeouts: `connectTimeout` (configurable via
|
|
8
|
+
`defaultTimeoutMs`) and `activityTimeout` (was hardcoded to 30s). The activity
|
|
9
|
+
timeout fires between stream chunk reads — if Dexie writes + Vuex reactivity for
|
|
10
|
+
a 2000-item chunk exceed 30s, the stream is aborted.
|
|
11
|
+
|
|
12
|
+
New fields:
|
|
13
|
+
- `RestProxy.defaultActivityTimeoutMs` — default for all streams (falls back to 30s)
|
|
14
|
+
- `SyncedDbConfig.streamActivityTimeoutMs` — threaded through SyncedDb → SyncEngine
|
|
15
|
+
→ RestProxy.findNewerManyStream(options.activityTimeoutMs)
|
|
16
|
+
|
|
3
17
|
## 0.1.209 (2026-06-25)
|
|
4
18
|
|
|
5
19
|
### Removed hardcoded `{ returnDeleted: true }` from sync specs
|
package/dist/index.js
CHANGED
|
@@ -3219,6 +3219,7 @@ var _SyncEngine = class _SyncEngine {
|
|
|
3219
3219
|
let conflictsResolved = 0;
|
|
3220
3220
|
const collectionStats = {};
|
|
3221
3221
|
this.callOnSyncStart({ calledFrom, initialSync: false });
|
|
3222
|
+
const _perCollectionItems = /* @__PURE__ */ new Map();
|
|
3222
3223
|
try {
|
|
3223
3224
|
this.deps.cancelRestUploadTimer();
|
|
3224
3225
|
await this.deps.awaitRestUpload();
|
|
@@ -3297,12 +3298,14 @@ var _SyncEngine = class _SyncEngine {
|
|
|
3297
3298
|
if (!config) return;
|
|
3298
3299
|
const state = collectionState.get(collection);
|
|
3299
3300
|
state.receivedCount += items.length;
|
|
3301
|
+
const _tProcess = performance.now();
|
|
3300
3302
|
const stats = await this.processIncomingServerData(
|
|
3301
3303
|
collection,
|
|
3302
3304
|
config,
|
|
3303
3305
|
items,
|
|
3304
3306
|
state.source
|
|
3305
3307
|
);
|
|
3308
|
+
const _processingMs = performance.now() - _tProcess;
|
|
3306
3309
|
state.conflicts += stats.conflictsResolved;
|
|
3307
3310
|
if (stats.maxTs) {
|
|
3308
3311
|
if (!state.maxTs || this.compareTimestamps(stats.maxTs, state.maxTs) > 0) {
|
|
@@ -3312,16 +3315,24 @@ var _SyncEngine = class _SyncEngine {
|
|
|
3312
3315
|
if (stats.updatedIds.length > 0) {
|
|
3313
3316
|
this.deps.broadcastUpdates({ [collection]: stats.updatedIds });
|
|
3314
3317
|
}
|
|
3315
|
-
|
|
3318
|
+
const isNewColl = !completedCollections.has(collection);
|
|
3319
|
+
if (isNewColl) {
|
|
3316
3320
|
completedCollections.add(collection);
|
|
3317
|
-
this.callbackSafe(this.callbacks.onSyncProgress, {
|
|
3318
|
-
phase: "server",
|
|
3319
|
-
collection,
|
|
3320
|
-
loaded: completedCollections.size,
|
|
3321
|
-
total: syncSpecs.length,
|
|
3322
|
-
items: items.length
|
|
3323
|
-
});
|
|
3324
3321
|
}
|
|
3322
|
+
_perCollectionItems.set(
|
|
3323
|
+
collection,
|
|
3324
|
+
(_perCollectionItems.get(collection) || 0) + items.length
|
|
3325
|
+
);
|
|
3326
|
+
this.callbackSafe(this.callbacks.onSyncProgress, {
|
|
3327
|
+
phase: "server",
|
|
3328
|
+
collection,
|
|
3329
|
+
loaded: completedCollections.size,
|
|
3330
|
+
total: syncSpecs.length,
|
|
3331
|
+
items: items.length,
|
|
3332
|
+
itemsCumulative: _perCollectionItems.get(collection),
|
|
3333
|
+
isNewCollection: isNewColl,
|
|
3334
|
+
processingMs: Math.round(_processingMs)
|
|
3335
|
+
});
|
|
3325
3336
|
},
|
|
3326
3337
|
{
|
|
3327
3338
|
onRequestBytes: (bytes) => {
|
|
@@ -3332,7 +3343,8 @@ var _SyncEngine = class _SyncEngine {
|
|
|
3332
3343
|
},
|
|
3333
3344
|
onResponseChunkBytes: (bytes) => {
|
|
3334
3345
|
responseBytes = (responseBytes != null ? responseBytes : 0) + bytes;
|
|
3335
|
-
}
|
|
3346
|
+
},
|
|
3347
|
+
activityTimeoutMs: this.deps.streamActivityTimeoutMs
|
|
3336
3348
|
}
|
|
3337
3349
|
),
|
|
3338
3350
|
"findNewerManyStream"
|
|
@@ -4140,10 +4152,12 @@ var _SyncEngine = class _SyncEngine {
|
|
|
4140
4152
|
}
|
|
4141
4153
|
async processIncomingServerData(collectionName, config, serverData, source = "incremental") {
|
|
4142
4154
|
if (serverData.length === 0) {
|
|
4143
|
-
return { conflictsResolved: 0, maxTs: void 0, updatedIds: [] };
|
|
4155
|
+
return { conflictsResolved: 0, maxTs: void 0, updatedIds: [], dexieMs: 0, inMemMs: 0 };
|
|
4144
4156
|
}
|
|
4145
4157
|
let maxTs;
|
|
4146
4158
|
let conflictsResolved = 0;
|
|
4159
|
+
let totalDexieMs = 0;
|
|
4160
|
+
let totalInMemMs = 0;
|
|
4147
4161
|
const allUpdatedIds = [];
|
|
4148
4162
|
const BATCH = _SyncEngine.SYNC_BATCH_SIZE;
|
|
4149
4163
|
for (let offset = 0; offset < serverData.length; offset += BATCH) {
|
|
@@ -4202,13 +4216,22 @@ var _SyncEngine = class _SyncEngine {
|
|
|
4202
4216
|
}
|
|
4203
4217
|
}
|
|
4204
4218
|
}
|
|
4219
|
+
let _timingDexieMs = 0;
|
|
4220
|
+
let _timingInMemMs = 0;
|
|
4205
4221
|
if (dexieBatch.length > 0) {
|
|
4222
|
+
const _t0 = performance.now();
|
|
4206
4223
|
await this.dexieDb.saveMany(collectionName, dexieBatch);
|
|
4224
|
+
_timingDexieMs = performance.now() - _t0;
|
|
4225
|
+
totalDexieMs += _timingDexieMs;
|
|
4207
4226
|
}
|
|
4208
4227
|
if (inMemSaveBatch.length > 0) {
|
|
4228
|
+
const _t1 = performance.now();
|
|
4209
4229
|
this.deps.writeToInMemBatch(collectionName, inMemSaveBatch, "upsert", {
|
|
4210
4230
|
source
|
|
4211
4231
|
});
|
|
4232
|
+
const _inMemMs = performance.now() - _t1;
|
|
4233
|
+
_timingInMemMs += _inMemMs;
|
|
4234
|
+
totalInMemMs += _inMemMs;
|
|
4212
4235
|
}
|
|
4213
4236
|
if (inMemDeleteIds.length > 0) {
|
|
4214
4237
|
this.deps.writeToInMemBatch(
|
|
@@ -4227,7 +4250,7 @@ var _SyncEngine = class _SyncEngine {
|
|
|
4227
4250
|
lastSyncTs: maxTs
|
|
4228
4251
|
});
|
|
4229
4252
|
}
|
|
4230
|
-
return { conflictsResolved, maxTs, updatedIds: allUpdatedIds };
|
|
4253
|
+
return { conflictsResolved, maxTs, updatedIds: allUpdatedIds, dexieMs: totalDexieMs, inMemMs: totalInMemMs };
|
|
4231
4254
|
}
|
|
4232
4255
|
// ============================================================
|
|
4233
4256
|
// Private Helpers
|
|
@@ -5087,6 +5110,7 @@ var _SyncedDb = class _SyncedDb {
|
|
|
5087
5110
|
},
|
|
5088
5111
|
getInMemById: (collection, id) => this.inMemDb.getById(collection, id),
|
|
5089
5112
|
withSyncTimeout: (promise, operation) => this.connectionManager.withSyncTimeout(promise, operation),
|
|
5113
|
+
streamActivityTimeoutMs: config.streamActivityTimeoutMs,
|
|
5090
5114
|
onSyncFailed: (reason) => this.connectionManager.callOnSyncFailed(reason),
|
|
5091
5115
|
flushAllPendingChanges: () => this.pendingChanges.flushAll(),
|
|
5092
5116
|
cancelRestUploadTimer: () => this.pendingChanges.cancelRestUploadTimer(),
|
|
@@ -10452,16 +10476,17 @@ var RestProxy = class {
|
|
|
10452
10476
|
this._lastRequestMs = 0;
|
|
10453
10477
|
this._totalRequestMs = 0;
|
|
10454
10478
|
this._requestCount = 0;
|
|
10455
|
-
var _a, _b, _c, _d, _e;
|
|
10479
|
+
var _a, _b, _c, _d, _e, _f;
|
|
10456
10480
|
this.endpoint = config.endpoint;
|
|
10457
10481
|
this.tenant = config.tenant;
|
|
10458
10482
|
this.apiKey = config.apiKey;
|
|
10459
10483
|
this.defaultTimeoutMs = (_a = config.defaultTimeoutMs) != null ? _a : DEFAULT_TIMEOUT;
|
|
10460
|
-
this.
|
|
10461
|
-
this.
|
|
10462
|
-
this.
|
|
10484
|
+
this.defaultActivityTimeoutMs = (_b = config.defaultActivityTimeoutMs) != null ? _b : 3e4;
|
|
10485
|
+
this.audit = (_c = config.audit) != null ? _c : {};
|
|
10486
|
+
this.timeRequestsPrint = (_d = config.timeRequestsPrint) != null ? _d : false;
|
|
10487
|
+
this.timeRequests = (_e = config.timeRequests) != null ? _e : this.timeRequestsPrint;
|
|
10463
10488
|
this.onProgressCallback = config.onProgressCallback;
|
|
10464
|
-
this.progressChunkSize = (
|
|
10489
|
+
this.progressChunkSize = (_f = config.progressChunkSize) != null ? _f : DEFAULT_PROGRESS_CHUNK_SIZE;
|
|
10465
10490
|
this.globalSignal = config.signal;
|
|
10466
10491
|
}
|
|
10467
10492
|
/** Set global abort signal */
|
|
@@ -10638,7 +10663,7 @@ var RestProxy = class {
|
|
|
10638
10663
|
async findNewerManyStream(spec, onChunk, options) {
|
|
10639
10664
|
var _a, _b, _c, _d, _e;
|
|
10640
10665
|
const connectTimeout = (_a = options == null ? void 0 : options.timeoutMs) != null ? _a : this.defaultTimeoutMs;
|
|
10641
|
-
const activityTimeout = (_b = options == null ? void 0 : options.activityTimeoutMs) != null ? _b :
|
|
10666
|
+
const activityTimeout = (_b = options == null ? void 0 : options.activityTimeoutMs) != null ? _b : this.defaultActivityTimeoutMs;
|
|
10642
10667
|
const externalSignal = (_c = options == null ? void 0 : options.signal) != null ? _c : this.globalSignal;
|
|
10643
10668
|
const startTime = this.timeRequests ? performance.now() : 0;
|
|
10644
10669
|
const fetchStart = performance.now();
|
|
@@ -13,6 +13,17 @@ export interface RestProxyConfig {
|
|
|
13
13
|
apiKey?: string;
|
|
14
14
|
/** Default timeout in ms (default: 5000) */
|
|
15
15
|
defaultTimeoutMs?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Default activity timeout for streaming responses (default: 30000).
|
|
18
|
+
*
|
|
19
|
+
* Unlike `defaultTimeoutMs` which covers the initial fetch() connection,
|
|
20
|
+
* this timeout fires if the gap between individual chunk reads exceeds
|
|
21
|
+
* the limit. Streaming syncs with many large collections (e.g. initial
|
|
22
|
+
* sync on a new device with 60+ collections and 2000-item chunks) need
|
|
23
|
+
* a higher value because Dexie writes + Vuex reactivity between reads
|
|
24
|
+
* can delay the next read() past the default 30s.
|
|
25
|
+
*/
|
|
26
|
+
defaultActivityTimeoutMs?: number;
|
|
16
27
|
/** Audit info for requests */
|
|
17
28
|
audit?: {
|
|
18
29
|
user?: string;
|
|
@@ -64,6 +75,7 @@ export declare class RestProxy implements I_RestInterface {
|
|
|
64
75
|
private tenant;
|
|
65
76
|
private apiKey?;
|
|
66
77
|
private defaultTimeoutMs;
|
|
78
|
+
private defaultActivityTimeoutMs;
|
|
67
79
|
private audit;
|
|
68
80
|
private timeRequests;
|
|
69
81
|
private timeRequestsPrint;
|
|
@@ -248,6 +248,9 @@ export interface SyncEngineCallbacks {
|
|
|
248
248
|
loaded: number;
|
|
249
249
|
total: number;
|
|
250
250
|
items: number;
|
|
251
|
+
itemsCumulative?: number;
|
|
252
|
+
isNewCollection?: boolean;
|
|
253
|
+
processingMs?: number;
|
|
251
254
|
}) => void;
|
|
252
255
|
onServerSyncStart?: (info: {
|
|
253
256
|
calledFrom?: string;
|
|
@@ -282,6 +285,8 @@ export interface SyncEngineDeps {
|
|
|
282
285
|
}) => void;
|
|
283
286
|
getInMemById: <T extends DbEntity>(collection: string, id: Id) => T | undefined;
|
|
284
287
|
withSyncTimeout: <T>(promise: Promise<T>, operation: string) => Promise<T>;
|
|
288
|
+
/** Activity timeout for streaming `findNewerManyStream` (ms). Default 30000. */
|
|
289
|
+
streamActivityTimeoutMs?: number;
|
|
285
290
|
/** Notify consumers that a sync cycle failed. Does not mutate online state. */
|
|
286
291
|
onSyncFailed: (reason: string) => void;
|
|
287
292
|
flushAllPendingChanges: () => Promise<void>;
|
|
@@ -133,6 +133,7 @@ export interface I_RestInterface {
|
|
|
133
133
|
findNewerManyStream<T>(spec: GetNewerSpec<T>[], onChunk: (collection: string, items: T[], specId?: string) => Promise<void>, options?: {
|
|
134
134
|
timeoutMs?: number;
|
|
135
135
|
signal?: AbortSignal;
|
|
136
|
+
activityTimeoutMs?: number;
|
|
136
137
|
onRequestBytes?: (bytes: number) => void;
|
|
137
138
|
onTtfbMs?: (ms: number) => void;
|
|
138
139
|
onResponseChunkBytes?: (bytes: number) => void;
|
|
@@ -592,6 +592,16 @@ export interface SyncedDbConfig {
|
|
|
592
592
|
restTimeoutMs?: number;
|
|
593
593
|
/** Timeout za sync REST klice v ms (default: 120000) - daljši ker sync prenaša več podatkov */
|
|
594
594
|
syncTimeoutMs?: number;
|
|
595
|
+
/**
|
|
596
|
+
* Activity timeout za streaming odgovore (default: 30000).
|
|
597
|
+
*
|
|
598
|
+
* Za razliko od `restTimeoutMs` (ki pokriva začetno fetch() povezavo),
|
|
599
|
+
* ta timeout sproži če je premor med posameznimi chunk read()-i daljši
|
|
600
|
+
* od meje. Initial sync na novi napravi (60+ kolekcij, 2000-item chunk-i)
|
|
601
|
+
* potrebuje višjo vrednost, ker Dexie writes + Vuex reactivity med read()-i
|
|
602
|
+
* lahko podaljšajo naslednji read() čez privzetih 30s.
|
|
603
|
+
*/
|
|
604
|
+
streamActivityTimeoutMs?: number;
|
|
595
605
|
/** Debounce čas za zapis v Dexie v ms (default: 200) */
|
|
596
606
|
debounceDexieWritesMs?: number;
|
|
597
607
|
/** Debounce čas za pošiljanje na REST v ms (default: 1000) - po uspešnem zapisu v Dexie */
|
|
@@ -664,6 +674,12 @@ export interface SyncedDbConfig {
|
|
|
664
674
|
loaded: number;
|
|
665
675
|
total: number;
|
|
666
676
|
items: number;
|
|
677
|
+
/** Cumulative items for this collection across all chunks so far */
|
|
678
|
+
itemsCumulative?: number;
|
|
679
|
+
/** True only for the first chunk of a new collection */
|
|
680
|
+
isNewCollection?: boolean;
|
|
681
|
+
/** Processing time for this chunk: Dexie save + InMem write (ms) */
|
|
682
|
+
processingMs?: number;
|
|
667
683
|
}) => void;
|
|
668
684
|
/**
|
|
669
685
|
* Callback when per-collection hydration status changes (hydration end,
|