@vue-skuilder/db 0.2.19 → 0.2.20
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/{SyncStrategy-BJMZq3WO.d.cts → SyncStrategy-CCU1H81I.d.cts} +8 -2
- package/dist/{SyncStrategy-BJMZq3WO.d.ts → SyncStrategy-CCU1H81I.d.ts} +8 -2
- package/dist/core/index.js +12 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +12 -2
- package/dist/core/index.mjs.map +1 -1
- package/dist/impl/couch/index.d.cts +18 -2
- package/dist/impl/couch/index.d.ts +18 -2
- package/dist/impl/couch/index.js +54 -6
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +54 -6
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.d.cts +1 -1
- package/dist/impl/static/index.d.ts +1 -1
- package/dist/impl/static/index.js +12 -2
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +12 -2
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/index.js +54 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/impl/common/BaseUserDB.ts +19 -2
- package/src/impl/common/SyncStrategy.ts +17 -4
- package/src/impl/couch/CouchDBSyncStrategy.ts +52 -4
package/dist/index.mjs
CHANGED
|
@@ -7361,22 +7361,60 @@ var init_CouchDBSyncStrategy = __esm({
|
|
|
7361
7361
|
* before we know what the remote already has, which is the conflict-leaf
|
|
7362
7362
|
* problem hydration exists to avoid. Local changes go up when startSync()
|
|
7363
7363
|
* takes over.
|
|
7364
|
+
*
|
|
7365
|
+
* Into an EMPTY local DB this skips deleted documents, because a mirror that
|
|
7366
|
+
* never held a document does not need to be told it was removed. That
|
|
7367
|
+
* matters more than it sounds: scheduled reviews (`card_review_*`) are
|
|
7368
|
+
* created and deleted once per review completed, so the changes feed is
|
|
7369
|
+
* dominated by tombstones and grows without bound, while the durable record
|
|
7370
|
+
* lives in card history. One real account measured 385 live documents behind
|
|
7371
|
+
* 8,370 deletions — an unfiltered pull moved 9,520 documents and took ~20s,
|
|
7372
|
+
* blowing the hydration timeout on a phone; filtered, the same pull moves
|
|
7373
|
+
* 404 and takes ~2s, reaching a byte-identical local state.
|
|
7374
|
+
*
|
|
7375
|
+
* The filter runs server-side, so `last_seq` still reports the source's true
|
|
7376
|
+
* sequence. Returning it lets startSync() begin the live pull from there
|
|
7377
|
+
* instead of re-walking the same history in the background — without that,
|
|
7378
|
+
* the cost is merely deferred, not removed.
|
|
7364
7379
|
*/
|
|
7365
7380
|
async hydrate(localDB, remoteDB) {
|
|
7366
|
-
const
|
|
7381
|
+
const pristine = (await localDB.info()).doc_count === 0;
|
|
7382
|
+
const replication = pouchdb_setup_default.replicate(
|
|
7383
|
+
remoteDB,
|
|
7384
|
+
localDB,
|
|
7385
|
+
pristine ? { selector: { _deleted: { $exists: false } } } : {}
|
|
7386
|
+
);
|
|
7367
7387
|
this.hydrationHandle = replication;
|
|
7368
7388
|
try {
|
|
7369
7389
|
const info = await replication;
|
|
7370
|
-
return {
|
|
7390
|
+
return {
|
|
7391
|
+
docsWritten: info.docs_written,
|
|
7392
|
+
// Only a pristine pull is a trustworthy starting point for the live
|
|
7393
|
+
// sync; otherwise leave startSync() to its own checkpoint.
|
|
7394
|
+
lastSeq: pristine ? info.last_seq : void 0
|
|
7395
|
+
};
|
|
7371
7396
|
} finally {
|
|
7372
7397
|
this.hydrationHandle = void 0;
|
|
7373
7398
|
}
|
|
7374
7399
|
}
|
|
7375
|
-
startSync(localDB, remoteDB) {
|
|
7400
|
+
startSync(localDB, remoteDB, since) {
|
|
7376
7401
|
if (localDB.name !== remoteDB.name) {
|
|
7377
7402
|
this.syncHandle = pouchdb_setup_default.sync(localDB, remoteDB, {
|
|
7378
7403
|
live: true,
|
|
7379
|
-
retry: true
|
|
7404
|
+
retry: true,
|
|
7405
|
+
// `since` applies to the pull only, and only when hydrate() just
|
|
7406
|
+
// established that local matches remote at that sequence. Without it,
|
|
7407
|
+
// a filtered hydration leaves the pull with no usable checkpoint (the
|
|
7408
|
+
// filter changes the replication id), so it restarts from zero and
|
|
7409
|
+
// re-walks in the background exactly the tombstone history hydration
|
|
7410
|
+
// just skipped — same work, now competing with the study session.
|
|
7411
|
+
//
|
|
7412
|
+
// Deliberately NOT persisted across launches: on later boots hydration
|
|
7413
|
+
// is skipped and the pull's own checkpoint is the correct resume
|
|
7414
|
+
// point, so a stored sequence could only be stale. If the app dies
|
|
7415
|
+
// before that first checkpoint is written, the next launch simply
|
|
7416
|
+
// walks the full feed once.
|
|
7417
|
+
...since !== void 0 ? { pull: { since } } : {}
|
|
7380
7418
|
});
|
|
7381
7419
|
}
|
|
7382
7420
|
}
|
|
@@ -7898,6 +7936,14 @@ var init_BaseUserDB = __esm({
|
|
|
7898
7936
|
_hydration = { state: "not-required" };
|
|
7899
7937
|
/** In-flight hydration, so concurrent callers can wait for a real answer. */
|
|
7900
7938
|
_hydrationPromise = null;
|
|
7939
|
+
/**
|
|
7940
|
+
* Sequence the local mirror was filled to by a hydration that succeeded in
|
|
7941
|
+
* THIS init(), handed to startSync() so the live pull can skip history it
|
|
7942
|
+
* would otherwise re-walk. Undefined whenever there is no such guarantee —
|
|
7943
|
+
* hydration skipped, not required, or failed. Never persisted; see the
|
|
7944
|
+
* `since` note in CouchDBSyncStrategy.startSync().
|
|
7945
|
+
*/
|
|
7946
|
+
_hydratedSeq;
|
|
7901
7947
|
/**
|
|
7902
7948
|
* How far the local mirror can be trusted, RIGHT NOW. See
|
|
7903
7949
|
* {@link UserHydrationStatus}.
|
|
@@ -8384,7 +8430,7 @@ Currently logged-in as ${this._username}.`
|
|
|
8384
8430
|
this.setDBandQ();
|
|
8385
8431
|
this._hydrationPromise = this.hydrateLocalMirror();
|
|
8386
8432
|
await this._hydrationPromise;
|
|
8387
|
-
this.syncStrategy.startSync(this.localDB, this.remoteDB);
|
|
8433
|
+
this.syncStrategy.startSync(this.localDB, this.remoteDB, this._hydratedSeq);
|
|
8388
8434
|
this.applyDesignDocs().catch((error) => {
|
|
8389
8435
|
log4(`Error in applyDesignDocs background task: ${error}`);
|
|
8390
8436
|
if (error && typeof error === "object") {
|
|
@@ -8412,6 +8458,7 @@ Currently logged-in as ${this._username}.`
|
|
|
8412
8458
|
* ceiling). Callers decide what a failure means for them.
|
|
8413
8459
|
*/
|
|
8414
8460
|
async hydrateLocalMirror() {
|
|
8461
|
+
this._hydratedSeq = void 0;
|
|
8415
8462
|
if (this.localDB.name === this.remoteDB.name || !this.syncStrategy.hydrate) {
|
|
8416
8463
|
this._hydration = { state: "not-required" };
|
|
8417
8464
|
return;
|
|
@@ -8423,11 +8470,12 @@ Currently logged-in as ${this._username}.`
|
|
|
8423
8470
|
this._hydration = { state: "hydrating" };
|
|
8424
8471
|
const start = Date.now();
|
|
8425
8472
|
try {
|
|
8426
|
-
const { docsWritten } = await withTimeout(
|
|
8473
|
+
const { docsWritten, lastSeq } = await withTimeout(
|
|
8427
8474
|
this.syncStrategy.hydrate(this.localDB, this.remoteDB),
|
|
8428
8475
|
HYDRATION_TIMEOUT_MS,
|
|
8429
8476
|
`Hydration of local mirror for ${this._username}`
|
|
8430
8477
|
);
|
|
8478
|
+
this._hydratedSeq = lastSeq;
|
|
8431
8479
|
await this.writeHydrationMarker();
|
|
8432
8480
|
this._hydration = {
|
|
8433
8481
|
state: "hydrated",
|