import prop from '@tinkoff/utils/object/prop' ; import propOr from '@tinkoff/utils/object/propOr' ; import { Plugin , Status } from '@tinkoff/request-core' ; import { shouldCacheExecute , getCacheKey as getCacheKeyUtil , metaTypes } from '@tinkoff/request-cache-utils' ; import { getStaleBackgroundRequestTimeout } from './utils' ; const CACHE_DEFAULT_TTL = 300000 ; declare module '@tinkoff/request-core/lib/types.h' { export interface Request { memoryCache ? : boolean ; memoryCacheForce ? : boolean ; memoryCacheTtl ? : number ; } } param { object } lruOptions param { boolean } shouldExecute param { boolean } allowStale param { number } staleTtl param { number } staleBackgroundRequestTimeout param { function } memoryConstructor param { function } getCacheKey export default ( { lruOptions = { max : 1000 , maxAge : CACHE_DEFAULT_TTL } , shouldExecute = true , allowStale = false , staleTtl = lruOptions . maxAge || CACHE_DEFAULT_TTL , staleBackgroundRequestTimeout = undefined , memoryConstructor = ( options ) => new ( require ( 'lru-cache' ) ) ( options ) , getCacheKey = undefined , } = { } ) : Plugin => { const lruCache = memoryConstructor ( { ... lruOptions , stale : true , } ) ; return { shouldExecute : shouldCacheExecute ( 'memory' , shouldExecute ) , init : ( context , next , makeRequest ) => { const cacheKey = getCacheKeyUtil ( context , getCacheKey ) ; if ( lruCache . has ( cacheKey ) ) { context . updateExternalMeta ( metaTypes . CACHE , { memoryCache : true , memoryCacheOutdated : false , } ) ; return next ( { status : Status . COMPLETE , response : lruCache . get ( cacheKey ) , } ) ; } const allowOutdated = propOr ( 'memoryCacheAllowStale' , allowStale , context . getRequest ( ) ) ; const outdated = allowOutdated && lruCache . peek ( cacheKey ) ; if ( outdated ) { const request = context . getRequest ( ) ; context . updateExternalMeta ( metaTypes . CACHE , { memoryCache : true , memoryCacheOutdated : true , } ) ; lruCache . set ( cacheKey , outdated , staleTtl ) ; setTimeout ( ( ) => makeRequest ( { ... request , timeout : getStaleBackgroundRequestTimeout ( { requestTimeout : request . timeout , configTimeout : staleBackgroundRequestTimeout , } ) , memoryCacheForce : true , memoryCacheBackground : true , } ) . catch ( ( ) => { } ) , 15 ) ; return next ( { status : Status . COMPLETE , response : outdated , } ) ; } next ( ) ; } , complete : ( context , next ) => { const cacheKey = getCacheKeyUtil ( context , getCacheKey ) ; const ttl = prop ( 'memoryCacheTtl' , context . getRequest ( ) ) ; lruCache . set ( cacheKey , context . getResponse ( ) , ttl ) ; context . updateExternalMeta ( metaTypes . CACHE , { memoryCacheBackground : prop ( 'memoryCacheBackground' , context . getRequest ( ) ) , } ) ; next ( ) ; } , } ; } ;