@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.d.cts
CHANGED
|
@@ -422,13 +422,6 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
422
422
|
* Cleared when the depletion-triggered replan fires (newQ exhausted).
|
|
423
423
|
*/
|
|
424
424
|
private _suppressQualityReplan;
|
|
425
|
-
/**
|
|
426
|
-
* Guards against infinite depletion-triggered replans. Set to true
|
|
427
|
-
* when a depletion replan fires; cleared when a replan produces
|
|
428
|
-
* content (newQ.length > 0 after replan) or when an explicit
|
|
429
|
-
* (non-auto) replan is requested.
|
|
430
|
-
*/
|
|
431
|
-
private _depletionReplanAttempted;
|
|
432
425
|
/**
|
|
433
426
|
* When > 0, the session timer cannot end the session. Decremented on
|
|
434
427
|
* each nextCard() draw. Set by replans that include `minFollowUpCards`.
|
|
@@ -521,6 +514,19 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
521
514
|
* newQ.peek(0) is the imminent draw we need to exclude.
|
|
522
515
|
*/
|
|
523
516
|
private _runReplan;
|
|
517
|
+
/**
|
|
518
|
+
* Run a replan, bypassing requestReplan()'s coalesce logic.
|
|
519
|
+
*
|
|
520
|
+
* Use this when correctness depends on a *fresh* pipeline run, not on
|
|
521
|
+
* the existence of *some* in-flight replan. Specifically: the
|
|
522
|
+
* wedge-breaker path in nextCard(), where coalescing into a previous
|
|
523
|
+
* run that we now know produced insufficient content would re-create
|
|
524
|
+
* the bug we're trying to prevent.
|
|
525
|
+
*
|
|
526
|
+
* Still tracks _replanPromise like requestReplan() does so concurrent
|
|
527
|
+
* observers (auto-trigger guards in nextCard()) see consistent state.
|
|
528
|
+
*/
|
|
529
|
+
private _replanUncoalesced;
|
|
524
530
|
/**
|
|
525
531
|
* Normalise the requestReplan argument. Accepts either a ReplanOptions
|
|
526
532
|
* object (new API) or a plain Record<string, unknown> (legacy callers
|
package/dist/index.d.ts
CHANGED
|
@@ -422,13 +422,6 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
422
422
|
* Cleared when the depletion-triggered replan fires (newQ exhausted).
|
|
423
423
|
*/
|
|
424
424
|
private _suppressQualityReplan;
|
|
425
|
-
/**
|
|
426
|
-
* Guards against infinite depletion-triggered replans. Set to true
|
|
427
|
-
* when a depletion replan fires; cleared when a replan produces
|
|
428
|
-
* content (newQ.length > 0 after replan) or when an explicit
|
|
429
|
-
* (non-auto) replan is requested.
|
|
430
|
-
*/
|
|
431
|
-
private _depletionReplanAttempted;
|
|
432
425
|
/**
|
|
433
426
|
* When > 0, the session timer cannot end the session. Decremented on
|
|
434
427
|
* each nextCard() draw. Set by replans that include `minFollowUpCards`.
|
|
@@ -521,6 +514,19 @@ declare class SessionController<TView = unknown> extends Loggable {
|
|
|
521
514
|
* newQ.peek(0) is the imminent draw we need to exclude.
|
|
522
515
|
*/
|
|
523
516
|
private _runReplan;
|
|
517
|
+
/**
|
|
518
|
+
* Run a replan, bypassing requestReplan()'s coalesce logic.
|
|
519
|
+
*
|
|
520
|
+
* Use this when correctness depends on a *fresh* pipeline run, not on
|
|
521
|
+
* the existence of *some* in-flight replan. Specifically: the
|
|
522
|
+
* wedge-breaker path in nextCard(), where coalescing into a previous
|
|
523
|
+
* run that we now know produced insufficient content would re-create
|
|
524
|
+
* the bug we're trying to prevent.
|
|
525
|
+
*
|
|
526
|
+
* Still tracks _replanPromise like requestReplan() does so concurrent
|
|
527
|
+
* observers (auto-trigger guards in nextCard()) see consistent state.
|
|
528
|
+
*/
|
|
529
|
+
private _replanUncoalesced;
|
|
524
530
|
/**
|
|
525
531
|
* Normalise the requestReplan argument. Accepts either a ReplanOptions
|
|
526
532
|
* object (new API) or a plain Record<string, unknown> (legacy callers
|
package/dist/index.js
CHANGED
|
@@ -7786,7 +7786,7 @@ Currently logged-in as ${this._username}.`
|
|
|
7786
7786
|
_rev: existingDoc._rev
|
|
7787
7787
|
});
|
|
7788
7788
|
} catch (e) {
|
|
7789
|
-
if (e
|
|
7789
|
+
if (e?.name === "not_found") {
|
|
7790
7790
|
await this.remoteDB.put(doc);
|
|
7791
7791
|
} else {
|
|
7792
7792
|
throw e;
|
|
@@ -7813,7 +7813,7 @@ Currently logged-in as ${this._username}.`
|
|
|
7813
7813
|
_rev: existingDoc._rev
|
|
7814
7814
|
});
|
|
7815
7815
|
} catch (e) {
|
|
7816
|
-
if (e
|
|
7816
|
+
if (e?.name === "conflict" && retries > 0) {
|
|
7817
7817
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
7818
7818
|
return this.applyDesignDoc(doc, retries - 1);
|
|
7819
7819
|
}
|
|
@@ -13387,13 +13387,6 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13387
13387
|
* Cleared when the depletion-triggered replan fires (newQ exhausted).
|
|
13388
13388
|
*/
|
|
13389
13389
|
_suppressQualityReplan = false;
|
|
13390
|
-
/**
|
|
13391
|
-
* Guards against infinite depletion-triggered replans. Set to true
|
|
13392
|
-
* when a depletion replan fires; cleared when a replan produces
|
|
13393
|
-
* content (newQ.length > 0 after replan) or when an explicit
|
|
13394
|
-
* (non-auto) replan is requested.
|
|
13395
|
-
*/
|
|
13396
|
-
_depletionReplanAttempted = false;
|
|
13397
13390
|
/**
|
|
13398
13391
|
* When > 0, the session timer cannot end the session. Decremented on
|
|
13399
13392
|
* each nextCard() draw. Set by replans that include `minFollowUpCards`.
|
|
@@ -13551,9 +13544,6 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13551
13544
|
*/
|
|
13552
13545
|
async requestReplan(options) {
|
|
13553
13546
|
const opts = this.normalizeReplanOptions(options);
|
|
13554
|
-
if (opts.hints || opts.label || opts.limit) {
|
|
13555
|
-
this._depletionReplanAttempted = false;
|
|
13556
|
-
}
|
|
13557
13547
|
const hasIntent = this._replanHasIntent(opts);
|
|
13558
13548
|
if (this._replanPromise) {
|
|
13559
13549
|
if (!hasIntent) {
|
|
@@ -13632,6 +13622,25 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13632
13622
|
}
|
|
13633
13623
|
await this._executeReplan(opts);
|
|
13634
13624
|
}
|
|
13625
|
+
/**
|
|
13626
|
+
* Run a replan, bypassing requestReplan()'s coalesce logic.
|
|
13627
|
+
*
|
|
13628
|
+
* Use this when correctness depends on a *fresh* pipeline run, not on
|
|
13629
|
+
* the existence of *some* in-flight replan. Specifically: the
|
|
13630
|
+
* wedge-breaker path in nextCard(), where coalescing into a previous
|
|
13631
|
+
* run that we now know produced insufficient content would re-create
|
|
13632
|
+
* the bug we're trying to prevent.
|
|
13633
|
+
*
|
|
13634
|
+
* Still tracks _replanPromise like requestReplan() does so concurrent
|
|
13635
|
+
* observers (auto-trigger guards in nextCard()) see consistent state.
|
|
13636
|
+
*/
|
|
13637
|
+
async _replanUncoalesced(opts) {
|
|
13638
|
+
const run = this._runReplan(opts);
|
|
13639
|
+
this._replanPromise = run.finally(() => {
|
|
13640
|
+
if (this._replanPromise === run) this._replanPromise = null;
|
|
13641
|
+
});
|
|
13642
|
+
await run;
|
|
13643
|
+
}
|
|
13635
13644
|
/**
|
|
13636
13645
|
* Normalise the requestReplan argument. Accepts either a ReplanOptions
|
|
13637
13646
|
* object (new API) or a plain Record<string, unknown> (legacy callers
|
|
@@ -13685,9 +13694,6 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13685
13694
|
`[Replan] Only ${wellIndicated}/${_SessionController.MIN_WELL_INDICATED} well-indicated cards after replan`
|
|
13686
13695
|
);
|
|
13687
13696
|
}
|
|
13688
|
-
if (this.newQ.length > 0) {
|
|
13689
|
-
this._depletionReplanAttempted = false;
|
|
13690
|
-
}
|
|
13691
13697
|
await this.hydrationService.ensureHydratedCards();
|
|
13692
13698
|
const labelTag = opts.label ? ` [${opts.label}]` : "";
|
|
13693
13699
|
this.log(`Replan complete${labelTag}: newQ now has ${this.newQ.length} cards (mode=${mode})`);
|
|
@@ -13966,21 +13972,13 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13966
13972
|
this.log("nextCard: awaiting in-flight replan before drawing");
|
|
13967
13973
|
await this._replanPromise;
|
|
13968
13974
|
}
|
|
13969
|
-
if (this.newQ.length <= 1 && this._secondsRemaining > 0 && !this._replanPromise
|
|
13975
|
+
if (this.newQ.length <= 1 && this._secondsRemaining > 0 && !this._replanPromise) {
|
|
13970
13976
|
this._suppressQualityReplan = false;
|
|
13971
|
-
this._depletionReplanAttempted = true;
|
|
13972
13977
|
const otherContent = this.reviewQ.length + this.failedQ.length;
|
|
13973
|
-
|
|
13974
|
-
this.
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
await this.requestReplan();
|
|
13978
|
-
} else {
|
|
13979
|
-
this.log(
|
|
13980
|
-
`[AutoReplan:depletion] newQ has ${this.newQ.length} card(s) (${otherContent} in other queues) with ${this._secondsRemaining}s remaining. Triggering background replan.`
|
|
13981
|
-
);
|
|
13982
|
-
void this.requestReplan();
|
|
13983
|
-
}
|
|
13978
|
+
this.log(
|
|
13979
|
+
`[AutoReplan:depletion] newQ has ${this.newQ.length} card(s) (${otherContent} in other queues) with ${this._secondsRemaining}s remaining. Triggering background replan.`
|
|
13980
|
+
);
|
|
13981
|
+
void this.requestReplan();
|
|
13984
13982
|
}
|
|
13985
13983
|
const REPLAN_BUFFER = 3;
|
|
13986
13984
|
if (!this._suppressQualityReplan && this._wellIndicatedRemaining <= REPLAN_BUFFER && this.newQ.length > 0 && !this._replanPromise) {
|
|
@@ -13994,6 +13992,27 @@ var SessionController = class _SessionController extends Loggable {
|
|
|
13994
13992
|
endSessionTracking();
|
|
13995
13993
|
return null;
|
|
13996
13994
|
}
|
|
13995
|
+
const WEDGE_MAX_EMPTY_STREAK = 3;
|
|
13996
|
+
const WEDGE_BACKOFF_MS = 250;
|
|
13997
|
+
let wedgeEmptyStreak = 0;
|
|
13998
|
+
while (this._secondsRemaining > 0 && this.newQ.length === 0 && this.reviewQ.length === 0 && this.failedQ.length === 0) {
|
|
13999
|
+
this.log(
|
|
14000
|
+
`[WedgeBreaker] All queues empty with ${this._secondsRemaining}s remaining. Running pipeline (attempt ${wedgeEmptyStreak + 1}/${WEDGE_MAX_EMPTY_STREAK}).`
|
|
14001
|
+
);
|
|
14002
|
+
await this._replanUncoalesced({ label: "wedge-breaker" });
|
|
14003
|
+
if (this.newQ.length === 0 && this.reviewQ.length === 0 && this.failedQ.length === 0) {
|
|
14004
|
+
wedgeEmptyStreak++;
|
|
14005
|
+
if (wedgeEmptyStreak >= WEDGE_MAX_EMPTY_STREAK) {
|
|
14006
|
+
this.log(
|
|
14007
|
+
`[WedgeBreaker] Pipeline returned no content ${WEDGE_MAX_EMPTY_STREAK} consecutive times. Giving up; session will end.`
|
|
14008
|
+
);
|
|
14009
|
+
break;
|
|
14010
|
+
}
|
|
14011
|
+
await new Promise((resolve) => setTimeout(resolve, WEDGE_BACKOFF_MS));
|
|
14012
|
+
} else {
|
|
14013
|
+
wedgeEmptyStreak = 0;
|
|
14014
|
+
}
|
|
14015
|
+
}
|
|
13997
14016
|
const MAX_SKIP = 20;
|
|
13998
14017
|
for (let attempt = 0; attempt < MAX_SKIP; attempt++) {
|
|
13999
14018
|
const nextItem = this._selectNextItemToHydrate();
|