@@ -56,6 +56,10 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
5656 private _latestTradesByDirectedPair : { [ key : string ] : TradeData } = { } ;
5757 private _blocksMetadata : BlockMetadata [ ] = [ ] ;
5858 private _tradingFeePPMByPair : { [ key : string ] : number } = { } ;
59+ private _isCacheInitialized : boolean = false ;
60+ private _handleCacheMiss :
61+ | ( ( token0 : string , token1 : string ) => Promise < void > )
62+ | undefined ;
5963 //#endregion private members
6064
6165 //#region serialization for persistent caching
@@ -173,6 +177,25 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
173177 }
174178 //#endregion serialization for persistent caching
175179
180+ public setCacheMissHandler (
181+ handler : ( token0 : string , token1 : string ) => Promise < void >
182+ ) : void {
183+ this . _handleCacheMiss = handler ;
184+ }
185+
186+ private async _checkAndHandleCacheMiss ( token0 : string , token1 : string ) {
187+ if (
188+ this . _isCacheInitialized ||
189+ ! this . _handleCacheMiss ||
190+ this . hasCachedPair ( token0 , token1 )
191+ )
192+ return ;
193+
194+ logger . debug ( 'Cache miss for pair' , token0 , token1 ) ;
195+ await this . _handleCacheMiss ( token0 , token1 ) ;
196+ logger . debug ( 'Cache miss for pair' , token0 , token1 , 'resolved' ) ;
197+ }
198+
176199 public clear ( silent : boolean = false ) : void {
177200 const pairs = Object . keys ( this . _strategiesByPair ) . map ( fromPairKey ) ;
178201 this . _strategiesByPair = { } ;
@@ -193,6 +216,7 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
193216 token0 : string ,
194217 token1 : string
195218 ) : Promise < EncodedStrategy [ ] | undefined > {
219+ await this . _checkAndHandleCacheMiss ( token0 , token1 ) ;
196220 const key = toPairKey ( token0 , token1 ) ;
197221 return this . _strategiesByPair [ key ] ;
198222 }
@@ -238,6 +262,7 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
238262 targetToken : string ,
239263 keepNonTradable : boolean = false
240264 ) : Promise < OrdersMap > {
265+ await this . _checkAndHandleCacheMiss ( sourceToken , targetToken ) ;
241266 const key = toDirectionKey ( sourceToken , targetToken ) ;
242267 const orders = this . _ordersByDirectedPair [ key ] || { } ;
243268
@@ -257,6 +282,7 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
257282 token0 : string ,
258283 token1 : string
259284 ) : Promise < TradeData | undefined > {
285+ await this . _checkAndHandleCacheMiss ( token0 , token1 ) ;
260286 const key = toPairKey ( token0 , token1 ) ;
261287 return this . _latestTradesByPair [ key ] ;
262288 }
@@ -265,6 +291,7 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
265291 sourceToken : string ,
266292 targetToken : string
267293 ) : Promise < TradeData | undefined > {
294+ await this . _checkAndHandleCacheMiss ( sourceToken , targetToken ) ;
268295 const key = toDirectionKey ( sourceToken , targetToken ) ;
269296 return this . _latestTradesByDirectedPair [ key ] ;
270297 }
@@ -281,6 +308,7 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
281308 token0 : string ,
282309 token1 : string
283310 ) : Promise < number | undefined > {
311+ await this . _checkAndHandleCacheMiss ( token0 , token1 ) ;
284312 const key = toPairKey ( token0 , token1 ) ;
285313 return this . _tradingFeePPMByPair [ key ] ;
286314 }
@@ -295,23 +323,10 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
295323 //#endregion public getters
296324
297325 //#region cache updates
298- /**
299- * This method is to be used when all the existing strategies of a pair are
300- * fetched and are to be stored in the cache.
301- * Once a pair is cached, the only way to update it is by using `applyEvents`.
302- * If all the strategies of a pair are deleted, the pair remains in the cache and there's
303- * no need to add it again.
304- * @param {string } token0 - address of the first token of the pair
305- * @param {string } token1 - address of the second token of the pair
306- * @param {EncodedStrategy[] } strategies - the strategies to be cached
307- * @throws {Error } if the pair is already cached
308- * @returns {void }
309- */
310- public addPair (
326+ private _addPair (
311327 token0 : string ,
312328 token1 : string ,
313- strategies : EncodedStrategy [ ] ,
314- noPairAddedEvent : boolean = false
329+ strategies : EncodedStrategy [ ]
315330 ) : void {
316331 logger . debug (
317332 'Adding pair with' ,
@@ -329,9 +344,56 @@ export class ChainCache extends (EventEmitter as new () => TypedEventEmitter<Cac
329344 this . _strategiesById [ strategy . id . toString ( ) ] = strategy ;
330345 this . _addStrategyOrders ( strategy ) ;
331346 } ) ;
332- if ( ! noPairAddedEvent ) {
333- logger . debug ( 'Emitting onPairAddedToCache' , token0 , token1 ) ;
334- this . emit ( 'onPairAddedToCache' , fromPairKey ( key ) ) ;
347+ }
348+
349+ /**
350+ * This method is to be used when all the existing strategies of a pair are
351+ * fetched and are to be stored in the cache.
352+ * Once a pair is cached, the only way to update it is by using `applyEvents`.
353+ * If all the strategies of a pair are deleted, the pair remains in the cache and there's
354+ * no need to add it again.
355+ * It emits an event `onPairAddedToCache` with the pair info.
356+ * @param {string } token0 - address of the first token of the pair
357+ * @param {string } token1 - address of the second token of the pair
358+ * @param {EncodedStrategy[] } strategies - the strategies to be cached
359+ * @throws {Error } if the pair is already cached
360+ * @returns {void }
361+ * @emits {onPairAddedToCache} - when the pair is added to the cache
362+ */
363+ public addPair (
364+ token0 : string ,
365+ token1 : string ,
366+ strategies : EncodedStrategy [ ]
367+ ) : void {
368+ this . _addPair ( token0 , token1 , strategies ) ;
369+ logger . debug ( 'Emitting onPairAddedToCache' , token0 , token1 ) ;
370+ this . emit ( 'onPairAddedToCache' , fromPairKey ( toPairKey ( token0 , token1 ) ) ) ;
371+ }
372+
373+ /**
374+ * This method is used when a number of pairs are fetched and are to be stored in the cache.
375+ * If this is the first time it is called with a non empty list of pairs it emits an event
376+ * to let know that the cache was initialized with data for the first time.
377+ *
378+ * @param {Array<{pair: TokenPair, strategies: EncodedStrategy[]}> } pairs - the pairs to add to the cache
379+ * @emits {onCacheInitialized} - when the cache is initialized with data for the first time
380+ * @throws {Error } if any pair is already cached
381+ * @returns {void }
382+ */
383+ public bulkAddPairs (
384+ pairs : {
385+ pair : TokenPair ;
386+ strategies : EncodedStrategy [ ] ;
387+ } [ ]
388+ ) : void {
389+ logger . debug ( 'Bulk adding pairs' , pairs ) ;
390+ for ( const pair of pairs ) {
391+ this . _addPair ( pair . pair [ 0 ] , pair . pair [ 1 ] , pair . strategies ) ;
392+ }
393+ if ( pairs . length > 0 && ! this . _isCacheInitialized ) {
394+ this . _isCacheInitialized = true ;
395+ logger . debug ( 'Emitting onCacheInitialized' ) ;
396+ this . emit ( 'onCacheInitialized' ) ;
335397 }
336398 }
337399
0 commit comments