cry-synced-db-client 2.0.8 → 2.0.10
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 +63 -6
- package/dist/src/db/sync/SyncEngine.d.ts +16 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3592,6 +3592,42 @@ var SyncEngine = class {
|
|
|
3592
3592
|
}
|
|
3593
3593
|
return out;
|
|
3594
3594
|
}
|
|
3595
|
+
/**
|
|
3596
|
+
* Diagnostic guard for the ACK writeback path: after pending writes have
|
|
3597
|
+
* been flushed and the row re-read, every plain scalar top-level field of
|
|
3598
|
+
* the just-uploaded delta should already be present with the uploaded
|
|
3599
|
+
* value. A mismatch means the re-read row still lags the server-confirmed
|
|
3600
|
+
* write — either a legitimate NEWER local edit landed after the upload
|
|
3601
|
+
* snapshot was taken (its own pending write will re-assert it), or a
|
|
3602
|
+
* residual race in the flush/re-fetch ordering. Either way, stamping the
|
|
3603
|
+
* new _rev onto such a row is exactly the mechanism that canonized stale
|
|
3604
|
+
* content in the 2026-07-17 vbptuj/obravnave incident, so it must be
|
|
3605
|
+
* observable in production logs. Comparison is deliberately limited to
|
|
3606
|
+
* plain scalar top-level keys: dot/bracket paths and object/array values
|
|
3607
|
+
* are skipped (deep-equality cost + mongo key-order make them unreliable
|
|
3608
|
+
* for a hot-path check).
|
|
3609
|
+
*/
|
|
3610
|
+
warnIfRowLagsUploadedDelta(collection, freshItem, uploaded) {
|
|
3611
|
+
if (!uploaded) return;
|
|
3612
|
+
const mismatches = [];
|
|
3613
|
+
for (const key of Object.keys(uploaded)) {
|
|
3614
|
+
if (key === "_id" || key === "_lastUpdaterId") continue;
|
|
3615
|
+
if (key.includes(".") || key.includes("[")) continue;
|
|
3616
|
+
const up = uploaded[key];
|
|
3617
|
+
if (up !== null && typeof up === "object") continue;
|
|
3618
|
+
const local = freshItem[key];
|
|
3619
|
+
if (local !== up) {
|
|
3620
|
+
mismatches.push(
|
|
3621
|
+
`${key} (local=${JSON.stringify(local)}, uploaded=${JSON.stringify(up)})`
|
|
3622
|
+
);
|
|
3623
|
+
}
|
|
3624
|
+
}
|
|
3625
|
+
if (mismatches.length > 0) {
|
|
3626
|
+
console.warn(
|
|
3627
|
+
`[SyncEngine] ACK writeback: re-read row lags uploaded delta for ${collection}:${String(freshItem._id)} \u2014 ${mismatches.join(", ")}`
|
|
3628
|
+
);
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3595
3631
|
/**
|
|
3596
3632
|
* Upload dirty items for all collections.
|
|
3597
3633
|
*/
|
|
@@ -3803,6 +3839,7 @@ var SyncEngine = class {
|
|
|
3803
3839
|
}
|
|
3804
3840
|
throw err;
|
|
3805
3841
|
}
|
|
3842
|
+
await this.deps.flushAllPendingChanges();
|
|
3806
3843
|
let sentCount = 0;
|
|
3807
3844
|
const collectionSentCounts = {};
|
|
3808
3845
|
for (const result of results) {
|
|
@@ -3914,10 +3951,16 @@ var SyncEngine = class {
|
|
|
3914
3951
|
const inMemUpdateBatch = [];
|
|
3915
3952
|
if (saveIds.length > 0) {
|
|
3916
3953
|
const freshItems = await this.dexieDb.getByIds(collection, saveIds);
|
|
3954
|
+
const uploadedById = this.uploadedSnapshotFor(collectionBatches, collection);
|
|
3917
3955
|
for (const freshItem of freshItems) {
|
|
3918
3956
|
if (!freshItem) continue;
|
|
3919
3957
|
const revTs = revById.get(String(freshItem._id));
|
|
3920
3958
|
if (!revTs) continue;
|
|
3959
|
+
this.warnIfRowLagsUploadedDelta(
|
|
3960
|
+
collection,
|
|
3961
|
+
freshItem,
|
|
3962
|
+
uploadedById.get(String(freshItem._id))
|
|
3963
|
+
);
|
|
3921
3964
|
freshItem._rev = revTs.rev;
|
|
3922
3965
|
freshItem._ts = revTs.ts;
|
|
3923
3966
|
dexieSaveBatch.push(freshItem);
|
|
@@ -5979,12 +6022,26 @@ var _SyncedDb = class _SyncedDb {
|
|
|
5979
6022
|
* @param calledFrom Diagnostic tag threaded through to upload callbacks
|
|
5980
6023
|
*/
|
|
5981
6024
|
async flushToServer(calledFrom) {
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
6025
|
+
try {
|
|
6026
|
+
if (!this.initialized) return;
|
|
6027
|
+
if (!this.connectionManager.canSync()) return;
|
|
6028
|
+
this.pendingChanges.cancelRestUploadTimer();
|
|
6029
|
+
await this.pendingChanges.flushAll();
|
|
6030
|
+
await this.pendingChanges.awaitRestUpload();
|
|
6031
|
+
await this.syncEngine.uploadDirtyItems(calledFrom);
|
|
6032
|
+
} catch (err) {
|
|
6033
|
+
console.error(`[SyncedDb] flushToServer ${(err == null ? void 0 : err.rejectMessage) || (err == null ? void 0 : err.message) || ""}`, {
|
|
6034
|
+
err,
|
|
6035
|
+
calledFrom,
|
|
6036
|
+
callstack: (() => {
|
|
6037
|
+
try {
|
|
6038
|
+
return new Error().stack;
|
|
6039
|
+
} catch (e) {
|
|
6040
|
+
return void 0;
|
|
6041
|
+
}
|
|
6042
|
+
})()
|
|
6043
|
+
});
|
|
6044
|
+
}
|
|
5988
6045
|
}
|
|
5989
6046
|
/**
|
|
5990
6047
|
* Returns when all collections were last successfully synced
|
|
@@ -54,6 +54,22 @@ export declare class SyncEngine implements I_SyncEngine {
|
|
|
54
54
|
* server-reconciled paths from local edits made during the round-trip.
|
|
55
55
|
*/
|
|
56
56
|
private uploadedSnapshotFor;
|
|
57
|
+
/**
|
|
58
|
+
* Diagnostic guard for the ACK writeback path: after pending writes have
|
|
59
|
+
* been flushed and the row re-read, every plain scalar top-level field of
|
|
60
|
+
* the just-uploaded delta should already be present with the uploaded
|
|
61
|
+
* value. A mismatch means the re-read row still lags the server-confirmed
|
|
62
|
+
* write — either a legitimate NEWER local edit landed after the upload
|
|
63
|
+
* snapshot was taken (its own pending write will re-assert it), or a
|
|
64
|
+
* residual race in the flush/re-fetch ordering. Either way, stamping the
|
|
65
|
+
* new _rev onto such a row is exactly the mechanism that canonized stale
|
|
66
|
+
* content in the 2026-07-17 vbptuj/obravnave incident, so it must be
|
|
67
|
+
* observable in production logs. Comparison is deliberately limited to
|
|
68
|
+
* plain scalar top-level keys: dot/bracket paths and object/array values
|
|
69
|
+
* are skipped (deep-equality cost + mongo key-order make them unreliable
|
|
70
|
+
* for a hot-path check).
|
|
71
|
+
*/
|
|
72
|
+
private warnIfRowLagsUploadedDelta;
|
|
57
73
|
/**
|
|
58
74
|
* Upload dirty items for all collections.
|
|
59
75
|
*/
|