@vue-skuilder/db 0.2.0 → 0.2.1

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/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.2.0",
7
+ "version": "0.2.1",
8
8
  "description": "Database layer for vue-skuilder",
9
9
  "main": "dist/index.js",
10
10
  "module": "dist/index.mjs",
@@ -48,7 +48,7 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@nilock2/pouchdb-authentication": "^1.0.2",
51
- "@vue-skuilder/common": "0.2.0",
51
+ "@vue-skuilder/common": "0.2.1",
52
52
  "cross-fetch": "^4.1.0",
53
53
  "moment": "^2.29.4",
54
54
  "pouchdb": "^9.0.0",
@@ -62,5 +62,5 @@
62
62
  "vite": "^8.0.0",
63
63
  "vitest": "^4.1.0"
64
64
  },
65
- "stableVersion": "0.2.0"
65
+ "stableVersion": "0.2.1"
66
66
  }
@@ -99,10 +99,16 @@ export const userDBDebugAPI = {
99
99
  */
100
100
  async showScheduledReviews(courseId?: string): Promise<void> {
101
101
  const userDB = getUserDB();
102
- if (!userDB) return;
102
+ if (!userDB) {
103
+ logger.info('[UserDB Debug] Data layer not available');
104
+ return;
105
+ }
106
+
107
+ logger.info(`[UserDB Debug] Fetching pending reviews${courseId ? ` for course: ${courseId}` : ''}...`);
103
108
 
104
109
  try {
105
110
  const reviews = await userDB.getPendingReviews(courseId);
111
+ logger.info(`[UserDB Debug] Got ${reviews.length} reviews`);
106
112
 
107
113
  // eslint-disable-next-line no-console
108
114
  console.group(`📅 Scheduled Reviews${courseId ? ` (${courseId})` : ''}`);
@@ -535,6 +535,20 @@ export class SessionController<TView = unknown> extends Loggable {
535
535
  */
536
536
  private static readonly WELL_INDICATED_SCORE = 0.10;
537
537
 
538
+ /**
539
+ * newQ length at or below which the opportunistic depletion-prefetch
540
+ * fires. Sets the lead time available for the background replan to land
541
+ * before the user actually empties the queue and falls into the
542
+ * (synchronous) wedge-breaker path.
543
+ *
544
+ * Set to a small absolute value (not a fraction of batch limit) because
545
+ * pipeline latency is roughly fixed regardless of batch size — what
546
+ * matters is "how many cards of user-pace do we have left." 3 cards
547
+ * × ~3-5s/card = ~10-15s of lead time, comfortably exceeding typical
548
+ * pipeline latency.
549
+ */
550
+ private static readonly DEPLETION_PREFETCH_THRESHOLD = 3;
551
+
538
552
  /**
539
553
  * Internal replan execution. Runs the pipeline, builds a new newQ,
540
554
  * atomically swaps it in, and triggers hydration for the new contents.
@@ -970,8 +984,16 @@ export class SessionController<TView = unknown> extends Loggable {
970
984
  // Opportunistic depletion: newQ running dry → background prefetch.
971
985
  // No latch — if this fires repeatedly when the pipeline keeps coming
972
986
  // back empty, the wedge-breaker's local backoff handles spin protection.
987
+ //
988
+ // Threshold sized to give the pipeline enough lead time to land the
989
+ // replan before the user empties the queue. Previously hardcoded to 1,
990
+ // which raced user pace against pipeline latency — fast users would hit
991
+ // an empty queue mid-session and feel the wedge-breaker's synchronous
992
+ // pipeline call as a "hang". DEPLETION_PREFETCH_THRESHOLD trades a
993
+ // slightly earlier prefetch (which is anyway desirable for content
994
+ // freshness) for a much more reliable lead time.
973
995
  if (
974
- this.newQ.length <= 1 &&
996
+ this.newQ.length <= SessionController.DEPLETION_PREFETCH_THRESHOLD &&
975
997
  this._secondsRemaining > 0 &&
976
998
  !this._replanPromise
977
999
  ) {