@vue-skuilder/db 0.1.36 → 0.1.39
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/core/index.js +2 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +2 -2
- package/dist/core/index.mjs.map +1 -1
- package/dist/impl/couch/index.js +2 -2
- package/dist/impl/couch/index.js.map +1 -1
- package/dist/impl/couch/index.mjs +2 -2
- package/dist/impl/couch/index.mjs.map +1 -1
- package/dist/impl/static/index.js +2 -2
- package/dist/impl/static/index.js.map +1 -1
- package/dist/impl/static/index.mjs +2 -2
- package/dist/impl/static/index.mjs.map +1 -1
- package/dist/index.d.cts +13 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.js +47 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/impl/common/BaseUserDB.ts +10 -2
- package/src/study/SessionController.ts +92 -64
package/dist/index.mjs
CHANGED
|
@@ -7767,7 +7767,7 @@ Currently logged-in as ${this._username}.`
|
|
|
7767
7767
|
_rev: existingDoc._rev
|
|
7768
7768
|
});
|
|
7769
7769
|
} catch (e) {
|
|
7770
|
-
if (e
|
|
7770
|
+
if (e?.name === "not_found") {
|
|
7771
7771
|
await this.remoteDB.put(doc);
|
|
7772
7772
|
} else {
|
|
7773
7773
|
throw e;
|
|
@@ -7794,7 +7794,7 @@ Currently logged-in as ${this._username}.`
|
|
|
7794
7794
|
_rev: existingDoc._rev
|
|
7795
7795
|
});
|
|
7796
7796
|
} catch (e) {
|
|
7797
|
-
if (e
|
|
7797
|
+
if (e?.name === "conflict" && retries > 0) {
|
|
7798
7798
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
7799
7799
|
return this.applyDesignDoc(doc, retries - 1);
|
|
7800
7800
|
}
|
|
@@ -13285,13 +13285,6 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13285
13285
|
* Cleared when the depletion-triggered replan fires (newQ exhausted).
|
|
13286
13286
|
*/
|
|
13287
13287
|
_suppressQualityReplan = false;
|
|
13288
|
-
/**
|
|
13289
|
-
* Guards against infinite depletion-triggered replans. Set to true
|
|
13290
|
-
* when a depletion replan fires; cleared when a replan produces
|
|
13291
|
-
* content (newQ.length > 0 after replan) or when an explicit
|
|
13292
|
-
* (non-auto) replan is requested.
|
|
13293
|
-
*/
|
|
13294
|
-
_depletionReplanAttempted = false;
|
|
13295
13288
|
/**
|
|
13296
13289
|
* When > 0, the session timer cannot end the session. Decremented on
|
|
13297
13290
|
* each nextCard() draw. Set by replans that include `minFollowUpCards`.
|
|
@@ -13449,9 +13442,6 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13449
13442
|
*/
|
|
13450
13443
|
async requestReplan(options) {
|
|
13451
13444
|
const opts = this.normalizeReplanOptions(options);
|
|
13452
|
-
if (opts.hints || opts.label || opts.limit) {
|
|
13453
|
-
this._depletionReplanAttempted = false;
|
|
13454
|
-
}
|
|
13455
13445
|
const hasIntent = this._replanHasIntent(opts);
|
|
13456
13446
|
if (this._replanPromise) {
|
|
13457
13447
|
if (!hasIntent) {
|
|
@@ -13530,6 +13520,25 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13530
13520
|
}
|
|
13531
13521
|
await this._executeReplan(opts);
|
|
13532
13522
|
}
|
|
13523
|
+
/**
|
|
13524
|
+
* Run a replan, bypassing requestReplan()'s coalesce logic.
|
|
13525
|
+
*
|
|
13526
|
+
* Use this when correctness depends on a *fresh* pipeline run, not on
|
|
13527
|
+
* the existence of *some* in-flight replan. Specifically: the
|
|
13528
|
+
* wedge-breaker path in nextCard(), where coalescing into a previous
|
|
13529
|
+
* run that we now know produced insufficient content would re-create
|
|
13530
|
+
* the bug we're trying to prevent.
|
|
13531
|
+
*
|
|
13532
|
+
* Still tracks _replanPromise like requestReplan() does so concurrent
|
|
13533
|
+
* observers (auto-trigger guards in nextCard()) see consistent state.
|
|
13534
|
+
*/
|
|
13535
|
+
async _replanUncoalesced(opts) {
|
|
13536
|
+
const run = this._runReplan(opts);
|
|
13537
|
+
this._replanPromise = run.finally(() => {
|
|
13538
|
+
if (this._replanPromise === run) this._replanPromise = null;
|
|
13539
|
+
});
|
|
13540
|
+
await run;
|
|
13541
|
+
}
|
|
13533
13542
|
/**
|
|
13534
13543
|
* Normalise the requestReplan argument. Accepts either a ReplanOptions
|
|
13535
13544
|
* object (new API) or a plain Record<string, unknown> (legacy callers
|
|
@@ -13583,9 +13592,6 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13583
13592
|
`[Replan] Only ${wellIndicated}/${_SessionController.MIN_WELL_INDICATED} well-indicated cards after replan`
|
|
13584
13593
|
);
|
|
13585
13594
|
}
|
|
13586
|
-
if (this.newQ.length > 0) {
|
|
13587
|
-
this._depletionReplanAttempted = false;
|
|
13588
|
-
}
|
|
13589
13595
|
await this.hydrationService.ensureHydratedCards();
|
|
13590
13596
|
const labelTag = opts.label ? ` [${opts.label}]` : "";
|
|
13591
13597
|
this.log(`Replan complete${labelTag}: newQ now has ${this.newQ.length} cards (mode=${mode})`);
|
|
@@ -13864,21 +13870,13 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13864
13870
|
this.log("nextCard: awaiting in-flight replan before drawing");
|
|
13865
13871
|
await this._replanPromise;
|
|
13866
13872
|
}
|
|
13867
|
-
if (this.newQ.length <= 1 && this._secondsRemaining > 0 && !this._replanPromise
|
|
13873
|
+
if (this.newQ.length <= 1 && this._secondsRemaining > 0 && !this._replanPromise) {
|
|
13868
13874
|
this._suppressQualityReplan = false;
|
|
13869
|
-
this._depletionReplanAttempted = true;
|
|
13870
13875
|
const otherContent = this.reviewQ.length + this.failedQ.length;
|
|
13871
|
-
|
|
13872
|
-
this.
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
await this.requestReplan();
|
|
13876
|
-
} else {
|
|
13877
|
-
this.log(
|
|
13878
|
-
`[AutoReplan:depletion] newQ has ${this.newQ.length} card(s) (${otherContent} in other queues) with ${this._secondsRemaining}s remaining. Triggering background replan.`
|
|
13879
|
-
);
|
|
13880
|
-
void this.requestReplan();
|
|
13881
|
-
}
|
|
13876
|
+
this.log(
|
|
13877
|
+
`[AutoReplan:depletion] newQ has ${this.newQ.length} card(s) (${otherContent} in other queues) with ${this._secondsRemaining}s remaining. Triggering background replan.`
|
|
13878
|
+
);
|
|
13879
|
+
void this.requestReplan();
|
|
13882
13880
|
}
|
|
13883
13881
|
const REPLAN_BUFFER = 3;
|
|
13884
13882
|
if (!this._suppressQualityReplan && this._wellIndicatedRemaining <= REPLAN_BUFFER && this.newQ.length > 0 && !this._replanPromise) {
|
|
@@ -13892,6 +13890,27 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13892
13890
|
endSessionTracking();
|
|
13893
13891
|
return null;
|
|
13894
13892
|
}
|
|
13893
|
+
const WEDGE_MAX_EMPTY_STREAK = 3;
|
|
13894
|
+
const WEDGE_BACKOFF_MS = 250;
|
|
13895
|
+
let wedgeEmptyStreak = 0;
|
|
13896
|
+
while (this._secondsRemaining > 0 && this.newQ.length === 0 && this.reviewQ.length === 0 && this.failedQ.length === 0) {
|
|
13897
|
+
this.log(
|
|
13898
|
+
`[WedgeBreaker] All queues empty with ${this._secondsRemaining}s remaining. Running pipeline (attempt ${wedgeEmptyStreak + 1}/${WEDGE_MAX_EMPTY_STREAK}).`
|
|
13899
|
+
);
|
|
13900
|
+
await this._replanUncoalesced({ label: "wedge-breaker" });
|
|
13901
|
+
if (this.newQ.length === 0 && this.reviewQ.length === 0 && this.failedQ.length === 0) {
|
|
13902
|
+
wedgeEmptyStreak++;
|
|
13903
|
+
if (wedgeEmptyStreak >= WEDGE_MAX_EMPTY_STREAK) {
|
|
13904
|
+
this.log(
|
|
13905
|
+
`[WedgeBreaker] Pipeline returned no content ${WEDGE_MAX_EMPTY_STREAK} consecutive times. Giving up; session will end.`
|
|
13906
|
+
);
|
|
13907
|
+
break;
|
|
13908
|
+
}
|
|
13909
|
+
await new Promise((resolve) => setTimeout(resolve, WEDGE_BACKOFF_MS));
|
|
13910
|
+
} else {
|
|
13911
|
+
wedgeEmptyStreak = 0;
|
|
13912
|
+
}
|
|
13913
|
+
}
|
|
13895
13914
|
const MAX_SKIP = 20;
|
|
13896
13915
|
for (let attempt = 0; attempt < MAX_SKIP; attempt++) {
|
|
13897
13916
|
const nextItem = this._selectNextItemToHydrate();
|