@@ -103,6 +103,7 @@ export class SessionController extends Loggable {
103103 private failedQ : ItemQueue < StudySessionFailedItem > = new ItemQueue < StudySessionFailedItem > ( ) ;
104104 private hydratedQ : ItemQueue < HydratedCard > = new ItemQueue < HydratedCard > ( ) ;
105105 private _currentCard : StudySessionItem | null = null ;
106+ private hydration_in_progress : boolean = false ;
106107
107108 private startTime : Date ;
108109 private endTime : Date ;
@@ -350,18 +351,31 @@ export class SessionController extends Loggable {
350351 }
351352 }
352353
353- public nextCard (
354+ public async nextCard (
354355 action :
355356 | 'dismiss-success'
356357 | 'dismiss-failed'
357358 | 'marked-failed'
358359 | 'dismiss-error' = 'dismiss-success'
359- ) : HydratedCard | null {
360+ ) : Promise < HydratedCard | null > {
360361 // dismiss (or sort to failedQ) the current card
361362 this . dismissCurrentCard ( action ) ;
362363
363- const card = this . hydratedQ . dequeue ( ) ;
364- void this . _fillHydratedQueue ( ) ;
364+ let card = this . hydratedQ . dequeue ( ) ;
365+
366+ // If no hydrated card but source cards available, wait for hydration
367+ if ( ! card && this . hasAvailableCards ( ) && ! this . hydration_in_progress ) {
368+ this . hydration_in_progress = true ;
369+ await this . _fillHydratedQueue ( ) ;
370+ this . hydration_in_progress = false ;
371+ card = this . hydratedQ . dequeue ( ) ;
372+ }
373+
374+ // Trigger background hydration to maintain cache (async, non-blocking)
375+ if ( this . hydratedQ . length < 3 ) {
376+ void this . _fillHydratedQueue ( ) ;
377+ }
378+
365379 return card ;
366380 }
367381
@@ -416,9 +430,19 @@ export class SessionController extends Loggable {
416430 }
417431 }
418432
433+ private hasAvailableCards ( ) : boolean {
434+ return this . reviewQ . length > 0 || this . newQ . length > 0 || this . failedQ . length > 0 ;
435+ }
436+
419437 private async _fillHydratedQueue ( ) {
420- const BATCH_SIZE = 5 ;
421- while ( this . hydratedQ . length < BATCH_SIZE ) {
438+ if ( this . hydration_in_progress ) {
439+ return ; // Prevent concurrent hydration
440+ }
441+
442+ const BUFFER_SIZE = 5 ;
443+ this . hydration_in_progress = true ;
444+
445+ while ( this . hydratedQ . length < BUFFER_SIZE ) {
422446 const nextItem = this . _selectNextItemToHydrate ( ) ;
423447 if ( ! nextItem ) {
424448 return ; // No more cards to hydrate
@@ -474,5 +498,7 @@ export class SessionController extends Loggable {
474498 }
475499 }
476500 }
501+
502+ this . hydration_in_progress = false ;
477503 }
478504}
0 commit comments