import { ActiveValueTracker } from "./active-value-tracker" ; export class BackgroundContextCache < T > { private readonly cache = new Map < string , T > ( ) ; private readonly activeUpdates = new Map < string , boolean > ( ) ; constructor ( private readonly activeContextTracker , private readonly getActiveContextValue , private readonly fallbackValue ) { this . activeContextTracker . activeChanged ( this . onActiveContextChanged , this ) ; const activeContext = this . activeContextTracker . active ( ) ; if ( activeContext ) { this . updateCache ( activeContext ) ; } } private onActiveContextChanged ( newContext ) { if ( newContext ) { this . updateCache ( newContext ) ; } } public async activeAsync ( ) { const contextName = await this . activeContextTracker . activeAsync ( ) ; if ( ! contextName ) { return this . fallbackValue ; } const result = this . cache . get ( contextName ) ; if ( result ) { return result ; } const value = await this . getActiveContextValue ( ) ; this . cache . set ( contextName , value ) ; return value ; } public changedActiveContextValue ( ) { const activeContext = this . activeContextTracker . active ( ) ; if ( activeContext ) { this . updateCache ( activeContext ) ; } } public active ( ) { const activeContext = this . activeContextTracker . active ( ) ; if ( ! activeContext ) { return this . fallbackValue ; } const result = this . cache . get ( activeContext ) ; if ( result ) { return result ; } this . updateCache ( activeContext ) ; return this . fallbackValue ; } private async updateCache ( activeContextName ) { if ( this . activeUpdates . get ( activeContextName ) ) { return ; } try { this . activeUpdates . set ( activeContextName , true ) ; const value = await this . getActiveContextValue ( ) ; if ( this . activeContextTracker . active ( ) === activeContextName ) { this . cache . set ( activeContextName , value ) ; } } finally { this . activeUpdates . delete ( activeContextName ) ; } } public invalidateActive ( ) { const activeContext = this . activeContextTracker . active ( ) ; if ( activeContext ) { this . updateCache ( activeContext ) ; } } }