@autofleet/matmon 2.4.9 → 2.4.10
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/lib/index.cjs +1 -1
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +78 -50
- package/lib/index.d.ts +78 -50
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
package/lib/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));const c=s(require(`lru-cache`)),l=s(require(`async-mutex`)),u=s(require(`dotenv`)),d=s(require(`@autofleet/logger`)),f=s(require(`redis`)),p=s(require(`redis-lock`)),m=s(require(`util`)),h=3e3,g=`mutex - locking timeout`,_=async(e,t)=>{let n=await e.acquire();try{await t()}finally{n()}},ee=()=>(0,l.withTimeout)(new l.Mutex,h,Error(g)),v=(0,d.default)();var y=v;u.default.config();const b=300,x=1e5,S={},C=({lifeTimeInSec:e,size:t=b})=>({max:Math.min(t,x),maxAge:process.env.NODE_ENV===`test`?0:1e3*e}),w=e=>(S[e]??=ee(),S[e]),T=e=>{S[e]&&delete S[e]},E=(e,t)=>new c.default(C({lifeTimeInSec:e,size:t})),D=process.env.IS_IN_MATMON_TESTING===`true`,O=process.env.NODE_ENV===`test`&&!D,k=async e=>{try{await e()}catch(e){y.error(`Failed to set in cache`,e)}},A=async({cacheKey:e,cacheGet:t,cacheSet:n,fetching:r,skipCache:i})=>{if(i||O){let e=await r();return await k(()=>n(e)),e}let a=null;try{await _(w(e),async()=>{a=await t(),a||(a=await r(),await k(()=>n(a))),T(e)})}catch{a=await r(),await k(()=>n(a)),T(e)}return a},j=(e,t)=>typeof e==`string`?e:e[t],M=({getFromCache:e,multiGetterFromCache:t,setInCache:n,setMultiInCache:r,getter:i,multiGetter:a,idField:o=`id`})=>async s=>{let c=new Map(s.filter(Boolean).map(e=>[j(e,o),e])),l=new Map,u=[...c.values()],d=await(t?.(u)??Promise.all(u.map(t=>e(t))));if(d.filter(Boolean).forEach(e=>{c.delete(j(e,o)),l.set(j(e,o),e)}),c.size>0){let e=await(a?.([...c.values()])??Promise.all([...c.values()].map(e=>i(e))));if(r&&e.length>0){let t=e.reduce((e,t)=>(e[j(t,o)]=t,e),{});await k(()=>r(t))}e.forEach(e=>{e&&(r||k(()=>n(e[o],e)),l.set(j(e,o),e))})}return s.map(e=>e?l.get(j(e,o)):null)};var N=class extends f.RedisError{innerError;message;constructor(e,t){super(),this.innerError=t,this.message=e}toString(){return`${this.message}: ${this.innerError}`}},te=class extends N{key;constructor(e,t,n){super(e,t),this.key=n}toString(){return`${this.message} (${this.key}): ${this.innerError}`}};const P=e=>{Object.keys(e).forEach(t=>{typeof e[t]==`function`&&(e[`${t}Async`]=(0,m.promisify)(e[t]),Object.defineProperty(e[`${t}Async`],`__isPromisified__`,{value:!0,configurable:!0,enumerable:!1,writable:!0}))})};P(f.default.RedisClient.prototype),P(f.default.Multi.prototype);const{env:F}=process,I=F.REDIS_HOST_NAME||`127.0.0.1`,L=F.REDIS_HOST_PORT||6379,R=F.AF_SERVICE_NAME,z=5e3,B=1e3,V=3600,H=R+`:`;if(!R)throw Error(`SERVICE_NAME cannot be null, please check your env.AF_SERVICE_NAME`);var U=class{client;locker;lockTimeout;lockDuration;locks={};baseTTL;lockRetries;keyPrefix=H;useLock;constructor(e){this.client=f.default.createClient({host:e.host||I,port:e.port||L}),this.locker=(0,m.promisify)((0,p.default)(this.client,e.lockRetries??10)),this.lockTimeout=e.lockTimeout??z,this.lockDuration=e.lockDuration??B,this.baseTTL=e.ttl??V,this.useLock=!!e.useLock}async get(e){let t=H+e,n;try{n=await this.client.getAsync(t)}catch(e){throw new N(`Failed to get a value`,e)}if(this.useLock){let e;try{e=await this.lock(t)}catch(e){throw new te(`Failed to lock key`,e,t)}this.locks[t]=e}return JSON.parse(n)}async getMultiple(e){let t=e.map(e=>H+e),n;try{if(t.length===0)return[];n=await this.client.mgetAsync(t)}catch(e){throw new N(`Failed to get a value`,e)}return n.map(e=>JSON.parse(e))}async set(e,t){let n=H+e,r=parseInt(String(this.baseTTL*(Math.random()+1)),10);try{await this.client.setAsync(n,JSON.stringify(t),`EX`,r),this.locks[n]&&(await this.locks[n](),delete this.locks[n])}catch(e){throw new N(`Failed to set a key-value pair`,e)}}async setMultiple(e){if(typeof e!=`object`){let e=new N(`keyValues must be an object`,Error(`keyValues must be an object`));throw y.error(`keyValues must be an object`,{error:e}),e}if(e==null||Object.keys(e).length===0)return;let t=Object.entries(e).map(([e,t])=>[H+e,JSON.stringify(t)]),n=Math.trunc(this.baseTTL*(Math.random()+1));try{let e=this.client.multi(),r=e.msetAsync(...t.flat());return t.map(([t])=>e.expireAsync(t,n)),await e.exec(),r}catch(e){throw new N(`Failed to set multiple key-value pairs`,e)}}async remove(e){let t=H+e;try{this.locks[t]&&(await this.locks[t](),delete this.locks[t]),await this.client.delAsync(t)}catch(e){throw new N(`Failed to delete key ${t}`,e)}}async removeMultiple(e){let t=e.map(e=>H+e);try{await this.client.delAsync(t)}catch(e){throw new N(`Failed to delete multiple keys ${t.join(`|`)}`,e)}}getClient(){return this.client}lock(e){return Promise.race([this.locker(e,this.lockDuration),new Promise((e,t)=>setTimeout(()=>t(),this.lockTimeout))])}},W=U;const{AF_SERVICE_NAME:G}=process.env,K=`ormCache`,q=[`afterSave`,`afterUpdate`,`afterDestroy`],J=[`beforeBulkUpdate`,`beforeBulkDestroy`],Y=(e,t)=>`${G}:${K}:${e}_${t}`,X=(e,t,n)=>`${G}:${K}:${e}_${t}_${n}_DEPENDENCIES`,Z=(e,t)=>{let n=e.associations.filter(e=>t[e.alias]).map(n=>{let r=n.accessKey,i=[];return Array.isArray(t[n.alias])?(t[n.alias].forEach(t=>{i.push(X(e.name,n.name,t[r])),n.innerAssociation&&t[n.innerAssociation.alias]&&i.push(X(e.name,n.innerAssociation.name,t[n.innerAssociation.alias][n.innerAssociation.accessKey]))}),i):[X(e.name,n.name,t[n.alias][r])]});return n.reduce((e,t)=>e.concat(t),[])},Q=(e,t,n)=>{let{transaction:r}=t;r?r.afterCommit(()=>n(e)):n(e)};var ne=class{constructor(e,t){this.ormInstance=e,this.debugMode=t}getModel(e){return this.ormInstance.models[e]}getModelDependencies(e){let{associations:t}=this.ormInstance.models[e];return[...Object.keys(t).map(e=>{let n=t[e],r={alias:n.as,name:n.target.name,accessKey:n.target.primaryKeyAttribute},{through:i}=n;if(i){let e=i.model;r.innerAssociation={alias:e.name,name:e.name,accessKey:e.primaryKeyAttribute}}return r})]}debug(e,t){this.debugMode&&y.info(`[ORM_CACHE Debug] ${e}`,t)}injectGetWithCacheFunction(e,t){let n=async n=>{let r=Z(t,n),i=Y(t.name,n.id);this.debug(`Adding dependencies`,{instanceKey:i,dependencyKeys:r});let a=e.getClient().multi(),o=(0,m.promisify)(a.exec).bind(a);return r.reduce((e,t)=>e.sadd(t,i),a),o()},r=this.getModel(t.name);r.findByPkCached=async(i,a,o)=>{let s=Y(t.name,i),c=JSON.parse(await e.getClient().getAsync(s));return c?(c=this.getModel(t.name).build(c,{isNewRecord:!1,include:o.include}),this.debug(`Found cached value`,{value:c,id:i,cacheKey:s})):(this.debug(`Value not found in cache, looking in db`,{id:i,cacheKey:s}),c=await r.scope(a).findByPk(i,o),this.debug(`Value from DB`,{value:c||`not found`,cacheKey:s}),await Promise.all([e.getClient().setAsync(s,JSON.stringify(c)),c&&n(c)])),c}}addInvalidationHooks(e,t){let n=async n=>{let r=Z(t,n),i=Y(t.name,n.id);this.debug(`Removing dependencies`,{instance:n,instanceKey:i,dependencyKeys:r});let a=e.getClient().multi(),o=(0,m.promisify)(a.exec).bind(a);return r.map(e=>a.srem(e,i)),a.del(i),o()},r=async(n,r)=>{let i=await e.getClient().smembersAsync(X(t.name,n,r));this.debug(`Invalidating dependent instances`,{dependentInstancesKeys:i});let a=e.getClient().multi(),o=(0,m.promisify)(a.exec).bind(a),s=await Promise.all(i.map(async n=>{let r=JSON.parse(await e.getClient().getAsync(n));if(!r)return[];let i=Z(t,r);return i.reduce((e,t)=>e.srem(t,n),a),a.del(n),i}));return this.debug(`Removing dependencies`,{dependentInstancesKeys:i,dependenciesToRemove:s}),o()},i=this.getModel(t.name);q.map(e=>i.addHook(e,(e,t)=>Q(e,t,e=>n(e)))),J.map(e=>i.addHook(e,e=>{e.individualHook=!0})),t.associations=this.getModelDependencies(t.name),this.debug(`Adding Invalidations Hooks to ${t.name}'s associations`,{associations:t.associations}),t.associations.forEach(e=>{let t=this.getModel(e.name);if(q.forEach(n=>t.addHook(n,(t,n)=>Q(t,n,t=>r(e.name,t[e.accessKey])))),J.forEach(e=>t.addHook(e,e=>{e.individualHook=!0})),e.innerAssociation){let t=this.getModel(e.innerAssociation.name);q.forEach(n=>t.addHook(n,(t,n)=>Q(t,n,t=>r(e.innerAssociation.name,t[e.innerAssociation.accessKey])))),J.map(e=>t.addHook(e,e=>{e.individualHook=!0}))}})}},re=class extends Error{};let $=function(e){return e.SEQUELIZE=`sequelize`,e}({});const ie=e=>{switch(e.type){case $.SEQUELIZE:return new ne(e.ormInstance,e.debug);default:throw new re(`ORM type ${e.type} is unsupported at the moment`)}},ae=e=>{let{models:t}=e;y.info(`Starting ORM Cache`,{options:e});let n=ie(e),r=new W({host:process.env.REDIS_HOST,port:Number.parseInt(process.env.REDIS_PORT,10)});t.map(e=>{n.addInvalidationHooks(r,e),n.injectGetWithCacheFunction(r,e)})};exports.ORMCache=ae,exports.ORMTypes=$,exports.RedisCache=W,exports.getMultipleWithCache=M,exports.getNewLRU=E,exports.getWithCacheSupport=A;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/lib/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache.ts","../src/locking.ts","../src/logger.ts","../src/redis/index.ts","../src/redis/errors.ts","../src/promise-utils.ts","../src/orm-cache/sequelize-adapter.ts","../src/orm-cache/errors.ts","../src/orm-cache/index.ts"],"names":["CACHE_LOCK_TIMEOUT_MILIS","LOCK_TIMEOUT_MESSAGE","wrapWithMutex","__name","mutex","funcToRun","release","acquire","getMutex","withTimeout","Mutex","Error","logger","CustomLogger","logger_default","dotenv","config","DEFAULT_CACHE_SIZE","MAX_SIZE","MUTEX_MAP","getOptions","lifeTimeInSec","size","max","Math","min","maxAge","process","env","NODE_ENV","getMutexByCacheKey","key","deleteMutexByCacheKey","getNewLRU","LRU","IN_LOCAL_TEST","IS_IN_MATMON_TESTING","IS_IN_SERVICE_TEST","tryToSetInCache","callback","e","error","getWithCacheSupport","cacheKey","cacheGet","cacheSet","fetching","skipCache","res","valueToReturn","getIdField","query","idField","getMultipleWithCache","getFromCache","multiGetterFromCache","setInCache","setMultiInCache","getter","multiGetter","queries","queriesMap","Map","filter","Boolean","map","resultMap","valuesToPullFromCache","values","Promise","all","forEach","value","delete","set","valuesFromGetter","id","length","setCacheObject","reduce","acc","get","RedisCacheError","RedisError","innerError","message","constructor","msg","err","toString","RedisLockError","promisifyAll","obj","Object","keys","promisify","defineProperty","configurable","enumerable","writable","redis","RedisClient","prototype","Multi","HOST","REDIS_HOST_NAME","PORT","REDIS_HOST_PORT","SERVICE_NAME","AF_SERVICE_NAME","DEFAULT_LOCK_TIMEOUT","DEFAULT_LOCK_DURATION","DEFAULT_BASE_TTL","KEY_PREFIX","RedisCache","client","locker","lockTimeout","lockDuration","locks","baseTTL","lockRetries","keyPrefix","useLock","options","createClient","host","port","redisLock","ttl","keyWithPrefix","getAsync","lock","JSON","parse","getMultiple","keysWithPrefix","mgetAsync","parseInt","String","random","setAsync","stringify","setMultiple","keyValues","keyValuesWithPrefix","entries","trunc","multi","setPromise","msetAsync","flat","expireAsync","exec","remove","delAsync","removeMultiple","join","getClient","race","_resolve","reject","setTimeout","redis_default","ORM_CACHE_PREFIX","INVALIDATION_HOOKS","BULK_HOOKS","generateInstanceKey","name","generateDependencyKey","modelName","associationName","associationId","getInstanceDependencyKeys","modelOptions","instance","associations","associationOptions","alias","accessKey","depKeys","Array","isArray","associationInstance","push","innerAssociation","flattenArray","array","concat","handleTransactionHook","func","transaction","afterCommit","SequelizeAdapter","ormInstance","debugMode","sequelize","debug","getModel","models","getModelDependencies","association","sequelizeAssociation","as","target","primaryKeyAttribute","through","relationModel","model","payload","info","injectGetWithCacheFunction","cache","addDependencies","dependencyKeys","instanceKey","addDependenciesMulti","addDependenciesMultiAsync","bind","sadd","findByPkCached","scopes","build","isNewRecord","include","scope","findByPk","addInvalidationHooks","invalidateModelInstance","removeMulti","removeMultiAsync","srem","del","invalidateModelInstanceByAssociation","dependentInstancesKeys","smembersAsync","dependenciesToRemove","hook","addHook","individualHook","associationModel","innerAssociationModel","innerAssociationInstance","UnsupportedOrmTypeError","K","ORMTypes","ORMInstanceFactory","type","ORMCache","adapter","REDIS_HOST","REDIS_PORT"],"mappings":"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","file":"index.cjs","sourcesContent":["import LRU from 'lru-cache';\n\nimport * as locking from './locking';\nimport dotenv from 'dotenv';\nimport type { MutexInterface } from 'async-mutex';\nimport logger from './logger';\n\ndotenv.config();\n\nconst DEFAULT_CACHE_SIZE = 300;\nconst MAX_SIZE = 100000;\nconst MUTEX_MAP = {} as Record<keyof any, undefined | MutexInterface>;\n\ninterface Options {\n lifeTimeInSec: number;\n size?: number;\n}\n\nconst getOptions = <K, V>({\n lifeTimeInSec,\n size = DEFAULT_CACHE_SIZE,\n}: Options): LRU.Options<K, V> => ({\n max: Math.min(size, MAX_SIZE),\n maxAge: process.env.NODE_ENV !== 'test' ? 1000 * lifeTimeInSec : 0,\n});\n\nconst getMutexByCacheKey = (key: keyof any) => {\n MUTEX_MAP[key] ??= locking.getMutex();\n return MUTEX_MAP[key];\n};\n\nconst deleteMutexByCacheKey = (key: keyof any) => {\n if (MUTEX_MAP[key]) {\n delete MUTEX_MAP[key];\n }\n};\n\nexport const getNewLRU = <K = unknown, V = unknown>(lifeTimeInSec: Options['lifeTimeInSec'], size?: Options['size']) => new LRU<K, V>(getOptions<K, V>({\n lifeTimeInSec,\n size,\n}));\n\ninterface GetWithCacheOptions<V = unknown> {\n cacheKey: string;\n cacheGet: () => Promise<V>;\n cacheSet: (value: V) => Promise<void>;\n fetching: () => Promise<V>;\n skipCache?: boolean;\n}\n\nconst IN_LOCAL_TEST = process.env.IS_IN_MATMON_TESTING === 'true';\nconst IS_IN_SERVICE_TEST = process.env.NODE_ENV === 'test' && !IN_LOCAL_TEST;\n\nconst tryToSetInCache = async (callback): Promise<void> => {\n try {\n await callback();\n } catch (e) {\n logger.error('Failed to set in cache', e);\n }\n};\n\nexport const getWithCacheSupport = async <V = unknown>({\n cacheKey,\n cacheGet,\n cacheSet,\n fetching,\n skipCache,\n}: GetWithCacheOptions<V>) => {\n if (skipCache || IS_IN_SERVICE_TEST) {\n const res = await fetching();\n await tryToSetInCache(() => cacheSet(res));\n return res;\n }\n let valueToReturn: Awaited<V> | null = null;\n try {\n await locking.wrapWithMutex(getMutexByCacheKey(cacheKey), async () => {\n valueToReturn = await cacheGet();\n if (!valueToReturn) {\n valueToReturn = await fetching();\n await tryToSetInCache(() => cacheSet(valueToReturn!));\n } else {\n // logger.info('get value from cache');\n }\n deleteMutexByCacheKey(cacheKey);\n });\n // retry without locking if failed\n } catch {\n valueToReturn = await fetching();\n await tryToSetInCache(() => cacheSet(valueToReturn!));\n deleteMutexByCacheKey(cacheKey);\n }\n return valueToReturn;\n};\n\n\nconst getIdField = (query: string | object, idField: keyof any): string => {\n if (typeof query === 'string') {\n return query;\n }\n return query[idField];\n};\n\ninterface GetMultipleWithCacheOptions<V = unknown> {\n getFromCache?: (query: any) => Promise<V>;\n multiGetterFromCache?: (queries: any[]) => Promise<V[]>;\n setInCache: (key: string, value: V) => Promise<void>;\n getter?: (query: any) => Promise<V>;\n multiGetter?: (queries: any[]) => Promise<V[]>;\n setMultiInCache?: (keyValues: Record<string, object>) => Promise<void>;\n idField?: string;\n}\n\nexport const getMultipleWithCache = <V = unknown>({\n getFromCache,\n multiGetterFromCache,\n setInCache,\n setMultiInCache,\n getter,\n multiGetter,\n idField = 'id',\n}: GetMultipleWithCacheOptions<V>) => async (queries: any[]) => {\n const queriesMap = new Map(queries.filter(Boolean).map(query => [getIdField(query, idField), query]));\n const resultMap = new Map<string, V>();\n\n const valuesToPullFromCache = [...queriesMap.values()];\n\n const valuesFromCache = await (\n multiGetterFromCache?.(valuesToPullFromCache) // Use multiGetterFromCache if it's provided\n ?? Promise.all(valuesToPullFromCache.map(query => getFromCache!(query))) // Otherwise, iterate over the queries with getFromCache\n );\n\n\n valuesFromCache.filter(Boolean).forEach((value) => {\n queriesMap.delete(getIdField(value as object, idField));\n resultMap.set(getIdField(value as object, idField), value);\n });\n\n if (queriesMap.size > 0) {\n const valuesFromGetter = await (\n multiGetter?.([...queriesMap.values()]) // Use multiGetter if it's provided\n ?? Promise.all([...queriesMap.values()].map(id => getter!(id))) // Otherwise, iterate over the queries with getter\n );\n\n if (setMultiInCache && valuesFromGetter.length > 0) {\n const setCacheObject = valuesFromGetter.reduce((acc, value) => {\n acc[getIdField(value as object, idField)] = value;\n return acc;\n }, {});\n await tryToSetInCache(() => setMultiInCache(setCacheObject));\n }\n\n valuesFromGetter.forEach((value) => {\n if (!value) {\n return;\n }\n if (!setMultiInCache) {\n void tryToSetInCache(() => setInCache(value[idField], value));\n }\n resultMap.set(getIdField(value as object, idField), value);\n });\n }\n\n return queries.map((query) => {\n if (!query) {\n return null;\n }\n return resultMap.get(getIdField(query, idField));\n });\n};\n","import { Mutex, type MutexInterface, withTimeout } from 'async-mutex';\n\nconst CACHE_LOCK_TIMEOUT_MILIS = 3000;\nconst LOCK_TIMEOUT_MESSAGE = 'mutex - locking timeout';\n\nexport const wrapWithMutex = async (mutex: MutexInterface, funcToRun: () => PromiseLike<void>) => {\n const release = await mutex.acquire();\n try {\n await funcToRun();\n } finally {\n release();\n }\n};\n\nexport const getMutex = (): MutexInterface => withTimeout(new Mutex(), CACHE_LOCK_TIMEOUT_MILIS, new Error(LOCK_TIMEOUT_MESSAGE));\n","import CustomLogger from '@autofleet/logger';\n\nconst logger = CustomLogger();\n\nexport default logger;\n","import redis from 'redis';\nimport redisLock from 'redis-lock';\nimport { promisify } from 'util';\nimport { RedisCacheError, RedisLockError } from './errors';\nimport logger from '../logger';\nimport { promisifyAll } from '../promise-utils';\n\npromisifyAll(redis.RedisClient.prototype);\npromisifyAll(redis.Multi.prototype);\n\nconst { env } = process;\n\nconst HOST = env.REDIS_HOST_NAME || '127.0.0.1';\nconst PORT = env.REDIS_HOST_PORT || 6379;\nconst SERVICE_NAME = env.AF_SERVICE_NAME;\nconst DEFAULT_LOCK_TIMEOUT = 5000;\nconst DEFAULT_LOCK_DURATION = 1000;\nconst DEFAULT_BASE_TTL = 3600;\nconst KEY_PREFIX = SERVICE_NAME + ':';\n\nif (!SERVICE_NAME) {\n throw new Error('SERVICE_NAME cannot be null, please check your env.AF_SERVICE_NAME');\n}\n\nclass RedisCache {\n // node redis client instance.\n private client: any;\n\n // A redis-lock instance.\n private locker: any;\n\n // The time that the cache will wait until a lock\n // will be considered as failed (in milliseconds).\n private lockTimeout: number;\n\n // The time that a key will be locked.\n private lockDuration: number;\n\n // A dictionary of key and its lock.\n locks: any;\n\n // The time that a key-value pair will exist in redis.\n // To this base time will be added between 1 to 2 milliseconds.\n private baseTTL: number;\n\n // The number of retries that we will try to lock a key in case of failure.\n private lockRetries: number;\n\n keyPrefix: string;\n\n useLock: boolean;\n\n constructor(options) {\n this.client = redis.createClient({\n host: options.host || HOST,\n port: options.port || PORT,\n });\n this.locker = promisify(redisLock(this.client, options.lockRetries ?? 10));\n this.lockTimeout = options.lockTimeout ?? DEFAULT_LOCK_TIMEOUT;\n this.lockDuration = options.lockDuration ?? DEFAULT_LOCK_DURATION;\n this.baseTTL = options.ttl ?? DEFAULT_BASE_TTL;\n this.locks = {};\n this.useLock = !!options.useLock;\n this.keyPrefix = KEY_PREFIX;\n }\n\n async get(key) {\n const keyWithPrefix = KEY_PREFIX + key;\n\n let value;\n try {\n // Try to get the value from redis.\n value = await this.client.getAsync(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to get a value', err);\n }\n\n if (this.useLock) {\n let lock;\n try {\n // Try to lock the key.\n lock = await this.lock(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisLockError('Failed to lock key', err, keyWithPrefix);\n }\n\n // If the lock did not fail, add it to a locks dictionary.\n this.locks[keyWithPrefix] = lock;\n }\n\n return JSON.parse(value);\n }\n\n async getMultiple(keys) {\n const keysWithPrefix = keys.map(key => KEY_PREFIX + key);\n let values;\n try {\n if (keysWithPrefix.length === 0) {\n return [];\n }\n // Try to get the value from redis.\n values = await this.client.mgetAsync(keysWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to get a value', err);\n }\n return values.map(value => JSON.parse(value));\n }\n\n async set(key, value) {\n const keyWithPrefix = KEY_PREFIX + key;\n const ttl = parseInt(String(this.baseTTL * (Math.random() + 1)), 10);\n try {\n await this.client.setAsync(keyWithPrefix, JSON.stringify(value), 'EX', ttl);\n if (this.locks[keyWithPrefix]) {\n await this.locks[keyWithPrefix]();\n delete this.locks[keyWithPrefix];\n }\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to set a key-value pair', err);\n }\n }\n\n async setMultiple(keyValues: Record<string, any>) {\n if (typeof keyValues !== 'object') {\n const error = new RedisCacheError('keyValues must be an object', new Error('keyValues must be an object'));\n logger.error('keyValues must be an object', { error });\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw error;\n }\n\n if (keyValues === null || keyValues === undefined || Object.keys(keyValues).length === 0) {\n return undefined;\n }\n\n const keyValuesWithPrefix = Object.entries(keyValues).map(([key, value]) => [KEY_PREFIX + key, JSON.stringify(value)]);\n const ttl = Math.trunc(this.baseTTL * (Math.random() + 1));\n try {\n const multi = this.client.multi();\n const setPromise = multi.msetAsync(...keyValuesWithPrefix.flat());\n keyValuesWithPrefix.map(([key]) => multi.expireAsync(key, ttl));\n await multi.exec();\n return setPromise;\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to set multiple key-value pairs', err);\n }\n }\n\n async remove(key) {\n const keyWithPrefix = KEY_PREFIX + key;\n try {\n if (this.locks[keyWithPrefix]) {\n await this.locks[keyWithPrefix]();\n delete this.locks[keyWithPrefix];\n }\n\n await this.client.delAsync(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError(`Failed to delete key ${keyWithPrefix}`, err);\n }\n }\n\n async removeMultiple(keys) {\n const keysWithPrefix = keys.map(key => KEY_PREFIX + key);\n try {\n await this.client.delAsync(keysWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError(`Failed to delete multiple keys ${keysWithPrefix.join('|')}`, err);\n }\n }\n\n getClient() {\n return this.client;\n }\n\n private lock(key) {\n return Promise.race([\n this.locker(key, this.lockDuration),\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n new Promise((_resolve, reject) => setTimeout(() => reject(), this.lockTimeout)),\n ]);\n }\n}\n\nexport default RedisCache;\n","import { RedisError } from 'redis';\n\nclass RedisCacheError extends RedisError {\n innerError: any;\n message: string;\n constructor(msg: string, err) {\n super();\n this.innerError = err;\n this.message = msg;\n }\n\n toString() {\n return `${this.message}: ${this.innerError}`;\n }\n}\n\nclass RedisLockError extends RedisCacheError {\n key: string;\n constructor(msg: string, err, key: string) {\n super(msg, err);\n this.key = key;\n }\n\n toString() {\n return `${this.message} (${this.key}): ${this.innerError}`;\n }\n}\n\nexport {\n RedisCacheError,\n RedisLockError,\n};\n","import { promisify } from 'util';\n\nexport const promisifyAll = (obj) => {\n Object.keys(obj).forEach((key) => {\n if (typeof obj[key] === 'function') {\n obj[`${key}Async`] = promisify(obj[key]);\n\n // To support the `isPromisified` check in `bluebird`, we need to set the `__isPromisified__` property to `true`.\n Object.defineProperty(obj[`${key}Async`], '__isPromisified__', {\n value: true,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n });\n};\n","import type { Sequelize } from 'sequelize';\nimport type { Adapter, AssociationOptions, ModelOptions } from './adapter';\nimport type RedisCache from '../redis';\nimport logger from '../logger';\nimport { promisify } from 'util';\n\nconst { AF_SERVICE_NAME } = process.env;\nconst ORM_CACHE_PREFIX = 'ormCache';\nconst INVALIDATION_HOOKS = ['afterSave', 'afterUpdate', 'afterDestroy'];\nconst BULK_HOOKS = ['beforeBulkUpdate', 'beforeBulkDestroy'];\n\nconst generateInstanceKey = (name: string, id: string): string =>\n `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${name}_${id}`;\n\nconst generateDependencyKey = (modelName: string, associationName: string, associationId: string): string =>\n `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${modelName}_${associationName}_${associationId}_DEPENDENCIES`;\n\nconst getInstanceDependencyKeys = (modelOptions: ModelOptions, instance): string[] => {\n const keys = modelOptions.associations!\n .filter((associationOptions: AssociationOptions) => instance[associationOptions.alias])\n .map((associationOptions: AssociationOptions): string[] => {\n const accessKey = associationOptions.accessKey!;\n const depKeys: string[] = [];\n if (Array.isArray(instance[associationOptions.alias])) {\n instance[associationOptions.alias].forEach((associationInstance) => {\n depKeys.push(generateDependencyKey(\n modelOptions.name,\n associationOptions.name,\n associationInstance[accessKey],\n ));\n if (associationOptions.innerAssociation && associationInstance[associationOptions.innerAssociation.alias]) {\n depKeys.push(generateDependencyKey(\n modelOptions.name,\n associationOptions.innerAssociation.name,\n associationInstance[associationOptions.innerAssociation.alias][associationOptions.innerAssociation.accessKey!],\n ));\n }\n });\n return depKeys;\n }\n return [\n generateDependencyKey(\n modelOptions.name,\n associationOptions.name,\n instance[associationOptions.alias][accessKey],\n ),\n ];\n });\n return keys.reduce((flattenArray, array) => flattenArray.concat(array), []);\n};\n\nconst handleTransactionHook = (instance, options, func) => {\n const { transaction } = options;\n if (transaction) {\n transaction.afterCommit(() => func(instance));\n } else {\n func(instance);\n }\n};\n\nexport default class SequelizeAdapter implements Adapter {\n ormInstance: Sequelize;\n debugMode: boolean;\n\n constructor(sequelize: Sequelize, debug) {\n this.ormInstance = sequelize;\n this.debugMode = debug;\n }\n\n getModel(modelName: string): any {\n return this.ormInstance.models[modelName];\n }\n\n getModelDependencies(modelName: string): AssociationOptions[] {\n const { associations } = this.ormInstance.models[modelName];\n return [\n ...Object.keys(associations).map((association) => {\n const sequelizeAssociation: any = associations[association];\n const associationOptions: AssociationOptions = {\n alias: sequelizeAssociation.as,\n name: sequelizeAssociation.target.name,\n accessKey: sequelizeAssociation.target.primaryKeyAttribute,\n };\n\n if (sequelizeAssociation.through) {\n const relationModel = sequelizeAssociation.through.model;\n associationOptions.innerAssociation = {\n alias: relationModel.name,\n name: relationModel.name,\n accessKey: relationModel.primaryKeyAttribute,\n };\n }\n\n return associationOptions;\n }),\n ];\n }\n\n debug(message, payload) {\n if (this.debugMode) {\n logger.info(`[ORM_CACHE Debug] ${message}`, payload);\n }\n }\n\n injectGetWithCacheFunction(cache: RedisCache, modelOptions: ModelOptions): void {\n const addDependencies = async (instance) => {\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n const instanceKey = generateInstanceKey(modelOptions.name, instance.id);\n this.debug('Adding dependencies', { instanceKey, dependencyKeys });\n const addDependenciesMulti = cache.getClient().multi();\n const addDependenciesMultiAsync = promisify(addDependenciesMulti.exec).bind(addDependenciesMulti);\n dependencyKeys.reduce((multi, key) => multi.sadd(key, instanceKey), addDependenciesMulti);\n return addDependenciesMultiAsync();\n };\n\n const model = this.getModel(modelOptions.name);\n model.findByPkCached = async (id: string, scopes: string[], options: any): Promise<any> => {\n const cacheKey = generateInstanceKey(modelOptions.name, id);\n let value = JSON.parse(await cache.getClient().getAsync(cacheKey));\n if (!value) {\n this.debug('Value not found in cache, looking in db', { id, cacheKey });\n value = await model.scope(scopes).findByPk(id, options);\n this.debug('Value from DB', { value: value || 'not found', cacheKey });\n await Promise.all([\n cache.getClient().setAsync(cacheKey, JSON.stringify(value)),\n value && addDependencies(value),\n ]);\n } else {\n value = this.getModel(modelOptions.name).build(value, { isNewRecord: false, include: options.include });\n this.debug('Found cached value', { value, id, cacheKey });\n }\n return value;\n };\n }\n\n addInvalidationHooks(cache: RedisCache, modelOptions: ModelOptions): void {\n const invalidateModelInstance = async (instance) => {\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n const instanceKey = generateInstanceKey(modelOptions.name, instance.id);\n this.debug('Removing dependencies', { instance, instanceKey, dependencyKeys });\n const removeMulti = cache.getClient().multi();\n const removeMultiAsync = promisify(removeMulti.exec).bind(removeMulti);\n dependencyKeys.map(key => removeMulti.srem(key, instanceKey));\n removeMulti.del(instanceKey);\n return removeMultiAsync();\n };\n\n const invalidateModelInstanceByAssociation = async (association, associationId) => {\n const dependentInstancesKeys = await cache.getClient().smembersAsync(generateDependencyKey(\n modelOptions.name,\n association,\n associationId,\n ));\n this.debug('Invalidating dependent instances', { dependentInstancesKeys });\n const removeMulti = cache.getClient().multi();\n const removeMultiAsync = promisify(removeMulti.exec).bind(removeMulti);\n const dependenciesToRemove = await Promise.all(dependentInstancesKeys.map(async (instanceKey) => {\n const instance = JSON.parse(await cache.getClient().getAsync(instanceKey));\n if (!instance) {\n return [];\n }\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n dependencyKeys.reduce((multi, key) => multi.srem(key, instanceKey), removeMulti);\n removeMulti.del(instanceKey);\n return dependencyKeys;\n }));\n this.debug('Removing dependencies', { dependentInstancesKeys, dependenciesToRemove });\n return removeMultiAsync();\n };\n\n const model = this.getModel(modelOptions.name);\n INVALIDATION_HOOKS.map(hook => model.addHook(hook, (instance, options) =>\n handleTransactionHook(instance, options, instance => invalidateModelInstance(instance))));\n BULK_HOOKS.map(hook => model.addHook(hook, options => options.individualHook = true));\n\n modelOptions.associations = this.getModelDependencies(modelOptions.name);\n this.debug(`Adding Invalidations Hooks to ${modelOptions.name}'s associations`, { associations: modelOptions.associations });\n modelOptions.associations.forEach((associationOptions) => {\n const associationModel = this.getModel(associationOptions.name);\n INVALIDATION_HOOKS.forEach(hook => associationModel.addHook(hook, (instance, options) =>\n handleTransactionHook(\n instance,\n options,\n associationInstance => invalidateModelInstanceByAssociation(\n associationOptions.name,\n associationInstance[associationOptions.accessKey!],\n ),\n ),\n ));\n BULK_HOOKS.forEach(hook => associationModel.addHook(hook, options => options.individualHook = true));\n\n if (associationOptions.innerAssociation) {\n const innerAssociationModel = this.getModel(associationOptions.innerAssociation.name);\n INVALIDATION_HOOKS.forEach(hook => innerAssociationModel.addHook(hook, (instance, options) =>\n handleTransactionHook(\n instance,\n options,\n innerAssociationInstance => invalidateModelInstanceByAssociation(\n associationOptions.innerAssociation!.name,\n innerAssociationInstance[associationOptions.innerAssociation!.accessKey!],\n ),\n ),\n ));\n BULK_HOOKS.map(hook => innerAssociationModel.addHook(hook, options => options.individualHook = true));\n }\n });\n }\n}\n","export class UnsupportedOrmTypeError extends Error {}\n","import type { Adapter, ModelOptions } from './adapter';\nimport SequelizeAdapter from './sequelize-adapter';\nimport { UnsupportedOrmTypeError } from './errors';\nimport RedisCache from '../redis';\nimport logger from '../logger';\n\nexport enum ORMTypes {\n SEQUELIZE = 'sequelize',\n}\n\ninterface ORMCacheOptions {\n type: ORMTypes;\n models: ModelOptions[];\n ormInstance: any;\n debug: boolean;\n}\n\nconst ORMInstanceFactory = (options: ORMCacheOptions): Adapter => {\n switch (options.type) {\n case ORMTypes.SEQUELIZE: {\n return new SequelizeAdapter(options.ormInstance, options.debug);\n }\n default: {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new UnsupportedOrmTypeError(`ORM type ${options.type} is unsupported at the moment`);\n }\n }\n};\n\nexport const ORMCache = (options: ORMCacheOptions): void => {\n const { models } = options;\n logger.info('Starting ORM Cache', { options });\n const adapter = ORMInstanceFactory(options);\n const cache = new RedisCache({\n host: process.env.REDIS_HOST,\n port: process.env.REDIS_PORT,\n });\n // eslint-disable-next-line array-callback-return\n models.map((modelOptions): void => {\n adapter.addInvalidationHooks(cache, modelOptions);\n adapter.injectGetWithCacheFunction(cache, modelOptions);\n });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["mutex: MutexInterface","funcToRun: () => PromiseLike<void>","Mutex","key: keyof any","lifeTimeInSec: Options['lifeTimeInSec']","size?: Options['size']","LRU","callback: () => void | PromiseLike<void>","valueToReturn: Awaited<V> | null","query: string | object","idField: keyof any","RedisError","msg: string","err: any","key: string","obj: object","options: RedisCacheOptions","key: string","keys: string[]","value: T","keyValues: Record<string, T>","name: string","id: string","modelName: string","associationName: string","associationId: string","modelOptions: ModelOptions","associationOptions: AssociationOptions","depKeys: string[]","ormInstance: Sequelize","debugMode: boolean","message: string","payload?: unknown","cache: RedisCache","scopes: string[]","options: Omit<NonNullFindOptions<Attributes<M>>, 'where'>","instance","options: ORMCacheOptions","RedisCache"],"sources":["../src/locking.ts","../src/logger.ts","../src/cache.ts","../src/redis/errors.ts","../src/promise-utils.ts","../src/redis/index.ts","../src/orm-cache/sequelize-adapter.ts","../src/orm-cache/errors.ts","../src/orm-cache/index.ts"],"sourcesContent":["import { Mutex, type MutexInterface, withTimeout } from 'async-mutex';\n\nconst CACHE_LOCK_TIMEOUT_MILIS = 3000;\nconst LOCK_TIMEOUT_MESSAGE = 'mutex - locking timeout';\n\nexport const wrapWithMutex = async (mutex: MutexInterface, funcToRun: () => PromiseLike<void>) => {\n const release = await mutex.acquire();\n try {\n await funcToRun();\n } finally {\n release();\n }\n};\n\nexport const getMutex = (): MutexInterface => withTimeout(new Mutex(), CACHE_LOCK_TIMEOUT_MILIS, new Error(LOCK_TIMEOUT_MESSAGE));\n","import CustomLogger from '@autofleet/logger';\n\nconst logger = CustomLogger();\n\nexport default logger;\n","import LRU from 'lru-cache';\n\nimport * as locking from './locking';\nimport dotenv from 'dotenv';\nimport type { MutexInterface } from 'async-mutex';\nimport logger from './logger';\n\ndotenv.config();\n\nconst DEFAULT_CACHE_SIZE = 300;\nconst MAX_SIZE = 100000;\nconst MUTEX_MAP = {} as Record<keyof any, undefined | MutexInterface>;\n\ninterface Options {\n lifeTimeInSec: number;\n size?: number;\n}\n\nconst getOptions = <K, V>({\n lifeTimeInSec,\n size = DEFAULT_CACHE_SIZE,\n}: Options): LRU.Options<K, V> => ({\n max: Math.min(size, MAX_SIZE),\n maxAge: process.env.NODE_ENV !== 'test' ? 1000 * lifeTimeInSec : 0,\n});\n\nconst getMutexByCacheKey = (key: keyof any): MutexInterface => {\n MUTEX_MAP[key] ??= locking.getMutex();\n return MUTEX_MAP[key];\n};\n\nconst deleteMutexByCacheKey = (key: keyof any): void => {\n if (MUTEX_MAP[key]) {\n delete MUTEX_MAP[key];\n }\n};\n\nexport const getNewLRU = <K = unknown, V = unknown>(lifeTimeInSec: Options['lifeTimeInSec'], size?: Options['size']): LRU<K, V> => new LRU<K, V>(getOptions<K, V>({\n lifeTimeInSec,\n size,\n}));\n\ninterface GetWithCacheOptions<V = unknown> {\n cacheKey: string;\n cacheGet: () => Promise<V>;\n cacheSet: (value: V) => Promise<void>;\n fetching: () => Promise<V>;\n skipCache?: boolean;\n}\n\nconst IN_LOCAL_TEST = process.env.IS_IN_MATMON_TESTING === 'true';\nconst IS_IN_SERVICE_TEST = process.env.NODE_ENV === 'test' && !IN_LOCAL_TEST;\n\nconst tryToSetInCache = async (callback: () => void | PromiseLike<void>): Promise<void> => {\n try {\n await callback();\n } catch (e) {\n logger.error('Failed to set in cache', e);\n }\n};\n\nexport const getWithCacheSupport = async <V = unknown>({\n cacheKey,\n cacheGet,\n cacheSet,\n fetching,\n skipCache,\n}: GetWithCacheOptions<V>): Promise<V> => {\n if (skipCache || IS_IN_SERVICE_TEST) {\n const res = await fetching();\n await tryToSetInCache(() => cacheSet(res));\n return res;\n }\n let valueToReturn: Awaited<V> | null = null;\n try {\n await locking.wrapWithMutex(getMutexByCacheKey(cacheKey), async () => {\n valueToReturn = await cacheGet();\n if (!valueToReturn) {\n valueToReturn = await fetching();\n await tryToSetInCache(() => cacheSet(valueToReturn!));\n } else {\n // logger.info('get value from cache');\n }\n deleteMutexByCacheKey(cacheKey);\n });\n // retry without locking if failed\n } catch {\n valueToReturn = await fetching();\n await tryToSetInCache(() => cacheSet(valueToReturn!));\n deleteMutexByCacheKey(cacheKey);\n }\n return valueToReturn!;\n};\n\n\nconst getIdField = (query: string | object, idField: keyof any): string => {\n if (typeof query === 'string') {\n return query;\n }\n return query[idField];\n};\n\ninterface GetMultipleWithCacheOptions<V = unknown> {\n getFromCache?: (query: any) => Promise<V>;\n multiGetterFromCache?: (queries: any[]) => Promise<V[]>;\n setInCache: (key: string, value: V) => Promise<void>;\n getter?: (query: any) => Promise<V>;\n multiGetter?: (queries: any[]) => Promise<V[]>;\n setMultiInCache?: (keyValues: Record<string, object>) => Promise<void>;\n idField?: string;\n}\n\nexport const getMultipleWithCache = <V = unknown>({\n getFromCache,\n multiGetterFromCache,\n setInCache,\n setMultiInCache,\n getter,\n multiGetter,\n idField = 'id',\n}: GetMultipleWithCacheOptions<V>): (queries: any[]) => Promise<(V | null | undefined)[]> => async (queries) => {\n const queriesMap = new Map(queries.filter(Boolean).map(query => [getIdField(query, idField), query]));\n const resultMap = new Map<string, V>();\n\n const valuesToPullFromCache = [...queriesMap.values()];\n\n const valuesFromCache = await (\n multiGetterFromCache?.(valuesToPullFromCache) // Use multiGetterFromCache if it's provided\n ?? Promise.all(valuesToPullFromCache.map(query => getFromCache!(query))) // Otherwise, iterate over the queries with getFromCache\n );\n\n\n valuesFromCache.filter(Boolean).forEach((value) => {\n queriesMap.delete(getIdField(value as object, idField));\n resultMap.set(getIdField(value as object, idField), value);\n });\n\n if (queriesMap.size > 0) {\n const valuesFromGetter = await (\n multiGetter?.([...queriesMap.values()]) // Use multiGetter if it's provided\n ?? Promise.all([...queriesMap.values()].map(id => getter!(id))) // Otherwise, iterate over the queries with getter\n );\n\n if (setMultiInCache && valuesFromGetter.length > 0) {\n const setCacheObject = valuesFromGetter.reduce((acc, value) => {\n acc[getIdField(value as object, idField)] = value;\n return acc;\n }, {});\n await tryToSetInCache(() => setMultiInCache(setCacheObject));\n }\n\n valuesFromGetter.forEach((value) => {\n if (!value) {\n return;\n }\n if (!setMultiInCache) {\n void tryToSetInCache(() => setInCache(value[idField], value));\n }\n resultMap.set(getIdField(value as object, idField), value);\n });\n }\n\n return queries.map((query) => {\n if (!query) {\n return null;\n }\n return resultMap.get(getIdField(query, idField));\n });\n};\n","import { RedisError } from 'redis';\n\nclass RedisCacheError extends RedisError {\n innerError: any;\n message: string;\n constructor(msg: string, err: any) {\n super();\n this.innerError = err;\n this.message = msg;\n }\n\n toString(): string {\n return `${this.message}: ${this.innerError}`;\n }\n}\n\nclass RedisLockError extends RedisCacheError {\n key: string;\n constructor(msg: string, err: any, key: string) {\n super(msg, err);\n this.key = key;\n }\n\n toString(): string {\n return `${this.message} (${this.key}): ${this.innerError}`;\n }\n}\n\nexport {\n RedisCacheError,\n RedisLockError,\n};\n","import { promisify } from 'util';\n\n\nexport const promisifyAll = (obj: object) => {\n Object.keys(obj).forEach((key) => {\n if (typeof obj[key] === 'function') {\n obj[`${key}Async`] = promisify(obj[key]);\n\n // To support the `isPromisified` check in `bluebird`, we need to set the `__isPromisified__` property to `true`.\n Object.defineProperty(obj[`${key}Async`], '__isPromisified__', {\n value: true,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n });\n};\n","import redis from 'redis';\nimport redisLock from 'redis-lock';\nimport { promisify } from 'util';\nimport { RedisCacheError, RedisLockError } from './errors';\nimport logger from '../logger';\nimport { promisifyAll } from '../promise-utils';\n\npromisifyAll(redis.RedisClient.prototype);\npromisifyAll(redis.Multi.prototype);\n\nconst { env } = process;\n\nconst HOST = env.REDIS_HOST_NAME || '127.0.0.1';\nconst PORT = env.REDIS_HOST_PORT || 6379;\nconst SERVICE_NAME = env.AF_SERVICE_NAME;\nconst DEFAULT_LOCK_TIMEOUT = 5000;\nconst DEFAULT_LOCK_DURATION = 1000;\nconst DEFAULT_BASE_TTL = 3600;\nconst KEY_PREFIX = SERVICE_NAME + ':';\n\nif (!SERVICE_NAME) {\n throw new Error('SERVICE_NAME cannot be null, please check your env.AF_SERVICE_NAME');\n}\n\ninterface RedisCacheOptions {\n host?: string;\n port?: number;\n lockRetries?: number;\n lockTimeout?: number;\n lockDuration?: number;\n ttl?: number;\n useLock?: boolean;\n}\n\nclass RedisCache {\n // node redis client instance.\n private client: any;\n\n // A redis-lock instance.\n private locker: (key: string, duration: number) => Promise<() => Promise<void>>;\n\n // The time that the cache will wait until a lock\n // will be considered as failed (in milliseconds).\n private lockTimeout: number;\n\n // The time that a key will be locked.\n private lockDuration: number;\n\n // A dictionary of key and its lock.\n locks: Record<string, () => Promise<void> | undefined> = {};\n\n // The time that a key-value pair will exist in redis.\n // To this base time will be added between 1 to 2 milliseconds.\n private baseTTL: number;\n\n // The number of retries that we will try to lock a key in case of failure.\n private lockRetries: number;\n\n keyPrefix = KEY_PREFIX;\n\n useLock: boolean;\n\n constructor(options: RedisCacheOptions) {\n this.client = redis.createClient({\n host: options.host || HOST,\n port: options.port || PORT,\n });\n this.locker = promisify(redisLock(this.client, options.lockRetries ?? 10));\n this.lockTimeout = options.lockTimeout ?? DEFAULT_LOCK_TIMEOUT;\n this.lockDuration = options.lockDuration ?? DEFAULT_LOCK_DURATION;\n this.baseTTL = options.ttl ?? DEFAULT_BASE_TTL;\n this.useLock = !!options.useLock;\n }\n\n async get<T = any>(key: string): Promise<T> {\n const keyWithPrefix = KEY_PREFIX + key;\n\n let value;\n try {\n // Try to get the value from redis.\n value = await this.client.getAsync(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to get a value', err);\n }\n\n if (this.useLock) {\n let lock;\n try {\n // Try to lock the key.\n lock = await this.lock(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisLockError('Failed to lock key', err, keyWithPrefix);\n }\n\n // If the lock did not fail, add it to a locks dictionary.\n this.locks[keyWithPrefix] = lock;\n }\n\n return JSON.parse(value);\n }\n\n async getMultiple<T = any>(keys: string[]): Promise<T[]> {\n const keysWithPrefix = keys.map(key => KEY_PREFIX + key);\n let values;\n try {\n if (keysWithPrefix.length === 0) {\n return [];\n }\n // Try to get the value from redis.\n values = await this.client.mgetAsync(keysWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to get a value', err);\n }\n return values.map(value => JSON.parse(value));\n }\n\n async set<T = any>(key: string, value: T): Promise<void> {\n const keyWithPrefix = KEY_PREFIX + key;\n const ttl = parseInt(String(this.baseTTL * (Math.random() + 1)), 10);\n try {\n await this.client.setAsync(keyWithPrefix, JSON.stringify(value), 'EX', ttl);\n if (this.locks[keyWithPrefix]) {\n await this.locks[keyWithPrefix]();\n delete this.locks[keyWithPrefix];\n }\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to set a key-value pair', err);\n }\n }\n\n async setMultiple<T = any>(keyValues: Record<string, T>): Promise<void> {\n if (typeof keyValues !== 'object') {\n const error = new RedisCacheError('keyValues must be an object', new Error('keyValues must be an object'));\n logger.error('keyValues must be an object', { error });\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw error;\n }\n\n if (keyValues === null || keyValues === undefined || Object.keys(keyValues).length === 0) {\n return undefined;\n }\n\n const keyValuesWithPrefix = Object.entries(keyValues).map(([key, value]) => [KEY_PREFIX + key, JSON.stringify(value)]);\n const ttl = Math.trunc(this.baseTTL * (Math.random() + 1));\n try {\n const multi = this.client.multi();\n const setPromise = multi.msetAsync(...keyValuesWithPrefix.flat());\n keyValuesWithPrefix.map(([key]) => multi.expireAsync(key, ttl));\n await multi.exec();\n return setPromise;\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to set multiple key-value pairs', err);\n }\n }\n\n async remove(key: string): Promise<void> {\n const keyWithPrefix = KEY_PREFIX + key;\n try {\n if (this.locks[keyWithPrefix]) {\n await this.locks[keyWithPrefix]();\n delete this.locks[keyWithPrefix];\n }\n\n await this.client.delAsync(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError(`Failed to delete key ${keyWithPrefix}`, err);\n }\n }\n\n async removeMultiple(keys: string[]): Promise<void> {\n const keysWithPrefix = keys.map(key => KEY_PREFIX + key);\n try {\n await this.client.delAsync(keysWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError(`Failed to delete multiple keys ${keysWithPrefix.join('|')}`, err);\n }\n }\n\n getClient(): any {\n return this.client;\n }\n\n private lock(key: string): Promise<() => Promise<void>> {\n return Promise.race([\n this.locker(key, this.lockDuration),\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n new Promise<never>((_resolve, reject) => setTimeout(() => reject(), this.lockTimeout)),\n ]);\n }\n}\n\nexport default RedisCache;\n","import type { Attributes, Model, ModelStatic, NonNullFindOptions, Sequelize } from 'sequelize';\nimport type { Adapter, AssociationOptions, ModelOptions } from './adapter';\nimport type RedisCache from '../redis';\nimport logger from '../logger';\nimport { promisify } from 'util';\n\nconst { AF_SERVICE_NAME } = process.env;\nconst ORM_CACHE_PREFIX = 'ormCache';\nconst INVALIDATION_HOOKS = ['afterSave', 'afterUpdate', 'afterDestroy'] as const;\nconst BULK_HOOKS = ['beforeBulkUpdate', 'beforeBulkDestroy'] as const;\n\nconst generateInstanceKey = (name: string, id: string): string =>\n `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${name}_${id}`;\n\nconst generateDependencyKey = (modelName: string, associationName: string, associationId: string): string =>\n `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${modelName}_${associationName}_${associationId}_DEPENDENCIES`;\n\nconst getInstanceDependencyKeys = (modelOptions: ModelOptions, instance): string[] => {\n const keys = modelOptions.associations!\n .filter((associationOptions: AssociationOptions) => instance[associationOptions.alias])\n .map((associationOptions: AssociationOptions): string[] => {\n const accessKey = associationOptions.accessKey!;\n const depKeys: string[] = [];\n if (Array.isArray(instance[associationOptions.alias])) {\n instance[associationOptions.alias].forEach((associationInstance) => {\n depKeys.push(generateDependencyKey(\n modelOptions.name,\n associationOptions.name,\n associationInstance[accessKey],\n ));\n if (associationOptions.innerAssociation && associationInstance[associationOptions.innerAssociation.alias]) {\n depKeys.push(generateDependencyKey(\n modelOptions.name,\n associationOptions.innerAssociation.name,\n associationInstance[associationOptions.innerAssociation.alias][associationOptions.innerAssociation.accessKey!],\n ));\n }\n });\n return depKeys;\n }\n return [\n generateDependencyKey(\n modelOptions.name,\n associationOptions.name,\n instance[associationOptions.alias][accessKey],\n ),\n ];\n });\n return keys.reduce((flattenArray, array) => flattenArray.concat(array), []);\n};\n\nconst handleTransactionHook = (instance, options, func) => {\n const { transaction } = options;\n if (transaction) {\n transaction.afterCommit(() => func(instance));\n } else {\n func(instance);\n }\n};\n\ndeclare module 'sequelize' {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Model {\n function findByPkCached<M extends Model>(\n this: ModelStatic<M>,\n identifier: string,\n scopes: string[],\n options: Omit<NonNullFindOptions<Attributes<M>>, 'where'>\n ): Promise<M>;\n }\n}\n\nexport default class SequelizeAdapter implements Adapter {\n constructor(public ormInstance: Sequelize, public debugMode: boolean) {\n }\n\n getModel(modelName: string): ModelStatic<Model> {\n return this.ormInstance.models[modelName];\n }\n\n getModelDependencies(modelName: string): AssociationOptions[] {\n const { associations } = this.ormInstance.models[modelName];\n return [\n ...Object.keys(associations).map((association) => {\n const sequelizeAssociation = associations[association];\n const associationOptions: AssociationOptions = {\n alias: sequelizeAssociation.as,\n name: sequelizeAssociation.target.name,\n accessKey: sequelizeAssociation.target.primaryKeyAttribute,\n };\n\n // @ts-expect-error through is not defined in the typings\n const { through } = sequelizeAssociation;\n if (through) {\n const relationModel = through.model;\n associationOptions.innerAssociation = {\n alias: relationModel.name,\n name: relationModel.name,\n accessKey: relationModel.primaryKeyAttribute,\n };\n }\n\n return associationOptions;\n }),\n ];\n }\n\n debug(message: string, payload?: unknown): void {\n if (this.debugMode) {\n logger.info(`[ORM_CACHE Debug] ${message}`, payload);\n }\n }\n\n injectGetWithCacheFunction(cache: RedisCache, modelOptions: ModelOptions): void {\n const addDependencies = async (instance) => {\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n const instanceKey = generateInstanceKey(modelOptions.name, instance.id);\n this.debug('Adding dependencies', { instanceKey, dependencyKeys });\n const addDependenciesMulti = cache.getClient().multi();\n const addDependenciesMultiAsync = promisify(addDependenciesMulti.exec).bind(addDependenciesMulti);\n dependencyKeys.reduce((multi, key) => multi.sadd(key, instanceKey), addDependenciesMulti);\n return addDependenciesMultiAsync();\n };\n\n const model = this.getModel(modelOptions.name);\n model.findByPkCached = async <M extends Model>(id: string, scopes: string[], options: Omit<NonNullFindOptions<Attributes<M>>, 'where'>): Promise<M> => {\n const cacheKey = generateInstanceKey(modelOptions.name, id);\n let value = JSON.parse(await cache.getClient().getAsync(cacheKey));\n if (!value) {\n this.debug('Value not found in cache, looking in db', { id, cacheKey });\n value = await model.scope(scopes).findByPk(id, options);\n this.debug('Value from DB', { value: value || 'not found', cacheKey });\n await Promise.all([\n cache.getClient().setAsync(cacheKey, JSON.stringify(value)),\n value && addDependencies(value),\n ]);\n } else {\n value = this.getModel(modelOptions.name).build(value, { isNewRecord: false, include: options.include });\n this.debug('Found cached value', { value, id, cacheKey });\n }\n return value;\n };\n }\n\n addInvalidationHooks(cache: RedisCache, modelOptions: ModelOptions): void {\n const invalidateModelInstance = async (instance) => {\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n const instanceKey = generateInstanceKey(modelOptions.name, instance.id);\n this.debug('Removing dependencies', { instance, instanceKey, dependencyKeys });\n const removeMulti = cache.getClient().multi();\n const removeMultiAsync = promisify(removeMulti.exec).bind(removeMulti);\n dependencyKeys.map(key => removeMulti.srem(key, instanceKey));\n removeMulti.del(instanceKey);\n return removeMultiAsync();\n };\n\n const invalidateModelInstanceByAssociation = async (association, associationId) => {\n const dependentInstancesKeys = await cache.getClient().smembersAsync(generateDependencyKey(\n modelOptions.name,\n association,\n associationId,\n ));\n this.debug('Invalidating dependent instances', { dependentInstancesKeys });\n const removeMulti = cache.getClient().multi();\n const removeMultiAsync = promisify(removeMulti.exec).bind(removeMulti);\n const dependenciesToRemove = await Promise.all(dependentInstancesKeys.map(async (instanceKey) => {\n const instance = JSON.parse(await cache.getClient().getAsync(instanceKey));\n if (!instance) {\n return [];\n }\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n dependencyKeys.reduce((multi, key) => multi.srem(key, instanceKey), removeMulti);\n removeMulti.del(instanceKey);\n return dependencyKeys;\n }));\n this.debug('Removing dependencies', { dependentInstancesKeys, dependenciesToRemove });\n return removeMultiAsync();\n };\n\n const model = this.getModel(modelOptions.name);\n INVALIDATION_HOOKS.map(hook => model.addHook(hook, (instance, options) =>\n handleTransactionHook(instance, options, instance => invalidateModelInstance(instance))));\n BULK_HOOKS.map(hook => model.addHook(hook, (options) => {\n options.individualHook = true;\n }));\n\n modelOptions.associations = this.getModelDependencies(modelOptions.name);\n this.debug(`Adding Invalidations Hooks to ${modelOptions.name}'s associations`, { associations: modelOptions.associations });\n modelOptions.associations.forEach((associationOptions) => {\n const associationModel = this.getModel(associationOptions.name);\n INVALIDATION_HOOKS.forEach(hook => associationModel.addHook(hook, (instance, options) =>\n handleTransactionHook(\n instance,\n options,\n associationInstance => invalidateModelInstanceByAssociation(\n associationOptions.name,\n associationInstance[associationOptions.accessKey!],\n ),\n ),\n ));\n BULK_HOOKS.forEach(hook => associationModel.addHook(hook, (options) => {\n options.individualHook = true;\n }));\n\n if (associationOptions.innerAssociation) {\n const innerAssociationModel = this.getModel(associationOptions.innerAssociation.name);\n INVALIDATION_HOOKS.forEach(hook => innerAssociationModel.addHook(hook, (instance, options) =>\n handleTransactionHook(\n instance,\n options,\n innerAssociationInstance => invalidateModelInstanceByAssociation(\n associationOptions.innerAssociation!.name,\n innerAssociationInstance[associationOptions.innerAssociation!.accessKey!],\n ),\n ),\n ));\n BULK_HOOKS.map(hook => innerAssociationModel.addHook(hook, (options) => {\n options.individualHook = true;\n }));\n }\n });\n }\n}\n","export class UnsupportedOrmTypeError extends Error {}\n","import type { Adapter, ModelOptions } from './adapter';\nimport SequelizeAdapter from './sequelize-adapter';\nimport { UnsupportedOrmTypeError } from './errors';\nimport RedisCache from '../redis';\nimport logger from '../logger';\n\nexport enum ORMTypes {\n SEQUELIZE = 'sequelize',\n}\n\ninterface ORMCacheOptions {\n type: ORMTypes;\n models: ModelOptions[];\n ormInstance: any;\n debug: boolean;\n}\n\nconst ORMInstanceFactory = (options: ORMCacheOptions): Adapter => {\n switch (options.type) {\n case ORMTypes.SEQUELIZE: {\n return new SequelizeAdapter(options.ormInstance, options.debug);\n }\n default: {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new UnsupportedOrmTypeError(`ORM type ${options.type} is unsupported at the moment`);\n }\n }\n};\n\nexport const ORMCache = (options: ORMCacheOptions): void => {\n const { models } = options;\n logger.info('Starting ORM Cache', { options });\n const adapter = ORMInstanceFactory(options);\n const cache = new RedisCache({\n host: process.env.REDIS_HOST,\n port: Number.parseInt(process.env.REDIS_PORT!, 10),\n });\n // eslint-disable-next-line array-callback-return\n models.map((modelOptions): void => {\n adapter.addInvalidationHooks(cache, modelOptions);\n adapter.injectGetWithCacheFunction(cache, modelOptions);\n });\n};\n"],"mappings":"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"}
|
package/lib/index.d.cts
CHANGED
|
@@ -1,70 +1,98 @@
|
|
|
1
|
-
import LRU from
|
|
1
|
+
import LRU from "lru-cache";
|
|
2
2
|
|
|
3
|
+
//#region src/cache.d.ts
|
|
3
4
|
interface Options {
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
lifeTimeInSec: number;
|
|
6
|
+
size?: number;
|
|
6
7
|
}
|
|
7
8
|
declare const getNewLRU: <K = unknown, V = unknown>(lifeTimeInSec: Options["lifeTimeInSec"], size?: Options["size"]) => LRU<K, V>;
|
|
8
9
|
interface GetWithCacheOptions<V = unknown> {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
cacheKey: string;
|
|
11
|
+
cacheGet: () => Promise<V>;
|
|
12
|
+
cacheSet: (value: V) => Promise<void>;
|
|
13
|
+
fetching: () => Promise<V>;
|
|
14
|
+
skipCache?: boolean;
|
|
14
15
|
}
|
|
15
|
-
declare const getWithCacheSupport: <V = unknown>({
|
|
16
|
+
declare const getWithCacheSupport: <V = unknown>({
|
|
17
|
+
cacheKey,
|
|
18
|
+
cacheGet,
|
|
19
|
+
cacheSet,
|
|
20
|
+
fetching,
|
|
21
|
+
skipCache
|
|
22
|
+
}: GetWithCacheOptions<V>) => Promise<V>;
|
|
16
23
|
interface GetMultipleWithCacheOptions<V = unknown> {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
getFromCache?: (query: any) => Promise<V>;
|
|
25
|
+
multiGetterFromCache?: (queries: any[]) => Promise<V[]>;
|
|
26
|
+
setInCache: (key: string, value: V) => Promise<void>;
|
|
27
|
+
getter?: (query: any) => Promise<V>;
|
|
28
|
+
multiGetter?: (queries: any[]) => Promise<V[]>;
|
|
29
|
+
setMultiInCache?: (keyValues: Record<string, object>) => Promise<void>;
|
|
30
|
+
idField?: string;
|
|
31
|
+
}
|
|
32
|
+
declare const getMultipleWithCache: <V = unknown>({
|
|
33
|
+
getFromCache,
|
|
34
|
+
multiGetterFromCache,
|
|
35
|
+
setInCache,
|
|
36
|
+
setMultiInCache,
|
|
37
|
+
getter,
|
|
38
|
+
multiGetter,
|
|
39
|
+
idField
|
|
40
|
+
}: GetMultipleWithCacheOptions<V>) => (queries: any[]) => Promise<(V | null | undefined)[]>;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/redis/index.d.ts
|
|
43
|
+
interface RedisCacheOptions {
|
|
44
|
+
host?: string;
|
|
45
|
+
port?: number;
|
|
46
|
+
lockRetries?: number;
|
|
47
|
+
lockTimeout?: number;
|
|
48
|
+
lockDuration?: number;
|
|
49
|
+
ttl?: number;
|
|
50
|
+
useLock?: boolean;
|
|
24
51
|
}
|
|
25
|
-
declare const getMultipleWithCache: <V = unknown>({ getFromCache, multiGetterFromCache, setInCache, setMultiInCache, getter, multiGetter, idField, }: GetMultipleWithCacheOptions<V>) => (queries: any[]) => Promise<(V | null | undefined)[]>;
|
|
26
|
-
|
|
27
52
|
declare class RedisCache {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
private client;
|
|
54
|
+
private locker;
|
|
55
|
+
private lockTimeout;
|
|
56
|
+
private lockDuration;
|
|
57
|
+
locks: Record<string, () => Promise<void> | undefined>;
|
|
58
|
+
private baseTTL;
|
|
59
|
+
private lockRetries;
|
|
60
|
+
keyPrefix: string;
|
|
61
|
+
useLock: boolean;
|
|
62
|
+
constructor(options: RedisCacheOptions);
|
|
63
|
+
get<T = any>(key: string): Promise<T>;
|
|
64
|
+
getMultiple<T = any>(keys: string[]): Promise<T[]>;
|
|
65
|
+
set<T = any>(key: string, value: T): Promise<void>;
|
|
66
|
+
setMultiple<T = any>(keyValues: Record<string, T>): Promise<void>;
|
|
67
|
+
remove(key: string): Promise<void>;
|
|
68
|
+
removeMultiple(keys: string[]): Promise<void>;
|
|
69
|
+
getClient(): any;
|
|
70
|
+
private lock;
|
|
46
71
|
}
|
|
47
|
-
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/orm-cache/adapter.d.ts
|
|
48
74
|
interface ModelOptions {
|
|
49
|
-
|
|
50
|
-
|
|
75
|
+
name: string;
|
|
76
|
+
associations?: AssociationOptions[];
|
|
51
77
|
}
|
|
52
78
|
interface AssociationOptions {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
79
|
+
name: string;
|
|
80
|
+
alias: string;
|
|
81
|
+
accessKey?: string;
|
|
82
|
+
innerAssociation?: AssociationOptions;
|
|
57
83
|
}
|
|
58
|
-
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/orm-cache/index.d.ts
|
|
59
86
|
declare enum ORMTypes {
|
|
60
|
-
|
|
87
|
+
SEQUELIZE = "sequelize",
|
|
61
88
|
}
|
|
62
89
|
interface ORMCacheOptions {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
90
|
+
type: ORMTypes;
|
|
91
|
+
models: ModelOptions[];
|
|
92
|
+
ormInstance: any;
|
|
93
|
+
debug: boolean;
|
|
67
94
|
}
|
|
68
95
|
declare const ORMCache: (options: ORMCacheOptions) => void;
|
|
69
|
-
|
|
96
|
+
//#endregion
|
|
70
97
|
export { ORMCache, ORMTypes, RedisCache, getMultipleWithCache, getNewLRU, getWithCacheSupport };
|
|
98
|
+
//# sourceMappingURL=index.d.cts.map
|
package/lib/index.d.ts
CHANGED
|
@@ -1,70 +1,98 @@
|
|
|
1
|
-
import LRU from
|
|
1
|
+
import LRU from "lru-cache";
|
|
2
2
|
|
|
3
|
+
//#region src/cache.d.ts
|
|
3
4
|
interface Options {
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
lifeTimeInSec: number;
|
|
6
|
+
size?: number;
|
|
6
7
|
}
|
|
7
8
|
declare const getNewLRU: <K = unknown, V = unknown>(lifeTimeInSec: Options["lifeTimeInSec"], size?: Options["size"]) => LRU<K, V>;
|
|
8
9
|
interface GetWithCacheOptions<V = unknown> {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
cacheKey: string;
|
|
11
|
+
cacheGet: () => Promise<V>;
|
|
12
|
+
cacheSet: (value: V) => Promise<void>;
|
|
13
|
+
fetching: () => Promise<V>;
|
|
14
|
+
skipCache?: boolean;
|
|
14
15
|
}
|
|
15
|
-
declare const getWithCacheSupport: <V = unknown>({
|
|
16
|
+
declare const getWithCacheSupport: <V = unknown>({
|
|
17
|
+
cacheKey,
|
|
18
|
+
cacheGet,
|
|
19
|
+
cacheSet,
|
|
20
|
+
fetching,
|
|
21
|
+
skipCache
|
|
22
|
+
}: GetWithCacheOptions<V>) => Promise<V>;
|
|
16
23
|
interface GetMultipleWithCacheOptions<V = unknown> {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
getFromCache?: (query: any) => Promise<V>;
|
|
25
|
+
multiGetterFromCache?: (queries: any[]) => Promise<V[]>;
|
|
26
|
+
setInCache: (key: string, value: V) => Promise<void>;
|
|
27
|
+
getter?: (query: any) => Promise<V>;
|
|
28
|
+
multiGetter?: (queries: any[]) => Promise<V[]>;
|
|
29
|
+
setMultiInCache?: (keyValues: Record<string, object>) => Promise<void>;
|
|
30
|
+
idField?: string;
|
|
31
|
+
}
|
|
32
|
+
declare const getMultipleWithCache: <V = unknown>({
|
|
33
|
+
getFromCache,
|
|
34
|
+
multiGetterFromCache,
|
|
35
|
+
setInCache,
|
|
36
|
+
setMultiInCache,
|
|
37
|
+
getter,
|
|
38
|
+
multiGetter,
|
|
39
|
+
idField
|
|
40
|
+
}: GetMultipleWithCacheOptions<V>) => (queries: any[]) => Promise<(V | null | undefined)[]>;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/redis/index.d.ts
|
|
43
|
+
interface RedisCacheOptions {
|
|
44
|
+
host?: string;
|
|
45
|
+
port?: number;
|
|
46
|
+
lockRetries?: number;
|
|
47
|
+
lockTimeout?: number;
|
|
48
|
+
lockDuration?: number;
|
|
49
|
+
ttl?: number;
|
|
50
|
+
useLock?: boolean;
|
|
24
51
|
}
|
|
25
|
-
declare const getMultipleWithCache: <V = unknown>({ getFromCache, multiGetterFromCache, setInCache, setMultiInCache, getter, multiGetter, idField, }: GetMultipleWithCacheOptions<V>) => (queries: any[]) => Promise<(V | null | undefined)[]>;
|
|
26
|
-
|
|
27
52
|
declare class RedisCache {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
private client;
|
|
54
|
+
private locker;
|
|
55
|
+
private lockTimeout;
|
|
56
|
+
private lockDuration;
|
|
57
|
+
locks: Record<string, () => Promise<void> | undefined>;
|
|
58
|
+
private baseTTL;
|
|
59
|
+
private lockRetries;
|
|
60
|
+
keyPrefix: string;
|
|
61
|
+
useLock: boolean;
|
|
62
|
+
constructor(options: RedisCacheOptions);
|
|
63
|
+
get<T = any>(key: string): Promise<T>;
|
|
64
|
+
getMultiple<T = any>(keys: string[]): Promise<T[]>;
|
|
65
|
+
set<T = any>(key: string, value: T): Promise<void>;
|
|
66
|
+
setMultiple<T = any>(keyValues: Record<string, T>): Promise<void>;
|
|
67
|
+
remove(key: string): Promise<void>;
|
|
68
|
+
removeMultiple(keys: string[]): Promise<void>;
|
|
69
|
+
getClient(): any;
|
|
70
|
+
private lock;
|
|
46
71
|
}
|
|
47
|
-
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/orm-cache/adapter.d.ts
|
|
48
74
|
interface ModelOptions {
|
|
49
|
-
|
|
50
|
-
|
|
75
|
+
name: string;
|
|
76
|
+
associations?: AssociationOptions[];
|
|
51
77
|
}
|
|
52
78
|
interface AssociationOptions {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
79
|
+
name: string;
|
|
80
|
+
alias: string;
|
|
81
|
+
accessKey?: string;
|
|
82
|
+
innerAssociation?: AssociationOptions;
|
|
57
83
|
}
|
|
58
|
-
|
|
84
|
+
//#endregion
|
|
85
|
+
//#region src/orm-cache/index.d.ts
|
|
59
86
|
declare enum ORMTypes {
|
|
60
|
-
|
|
87
|
+
SEQUELIZE = "sequelize",
|
|
61
88
|
}
|
|
62
89
|
interface ORMCacheOptions {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
90
|
+
type: ORMTypes;
|
|
91
|
+
models: ModelOptions[];
|
|
92
|
+
ormInstance: any;
|
|
93
|
+
debug: boolean;
|
|
67
94
|
}
|
|
68
95
|
declare const ORMCache: (options: ORMCacheOptions) => void;
|
|
69
|
-
|
|
96
|
+
//#endregion
|
|
70
97
|
export { ORMCache, ORMTypes, RedisCache, getMultipleWithCache, getNewLRU, getWithCacheSupport };
|
|
98
|
+
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"lru-cache";import{Mutex as t,withTimeout as n}from"async-mutex";import r from"dotenv";import i from"@autofleet/logger";import a,{RedisError as o}from"redis";import s from"redis-lock";import{promisify as c}from"util";const l=3e3,u=`mutex - locking timeout`,d=async(e,t)=>{let n=await e.acquire();try{await t()}finally{n()}},f=()=>n(new t,l,Error(u)),p=i();var m=p;r.config();const h=300,g=1e5,_={},v=({lifeTimeInSec:e,size:t=h})=>({max:Math.min(t,g),maxAge:process.env.NODE_ENV===`test`?0:1e3*e}),y=e=>(_[e]??=f(),_[e]),b=e=>{_[e]&&delete _[e]},x=(t,n)=>new e(v({lifeTimeInSec:t,size:n})),S=process.env.IS_IN_MATMON_TESTING===`true`,C=process.env.NODE_ENV===`test`&&!S,w=async e=>{try{await e()}catch(e){m.error(`Failed to set in cache`,e)}},T=async({cacheKey:e,cacheGet:t,cacheSet:n,fetching:r,skipCache:i})=>{if(i||C){let e=await r();return await w(()=>n(e)),e}let a=null;try{await d(y(e),async()=>{a=await t(),a||(a=await r(),await w(()=>n(a))),b(e)})}catch{a=await r(),await w(()=>n(a)),b(e)}return a},E=(e,t)=>typeof e==`string`?e:e[t],D=({getFromCache:e,multiGetterFromCache:t,setInCache:n,setMultiInCache:r,getter:i,multiGetter:a,idField:o=`id`})=>async s=>{let c=new Map(s.filter(Boolean).map(e=>[E(e,o),e])),l=new Map,u=[...c.values()],d=await(t?.(u)??Promise.all(u.map(t=>e(t))));if(d.filter(Boolean).forEach(e=>{c.delete(E(e,o)),l.set(E(e,o),e)}),c.size>0){let e=await(a?.([...c.values()])??Promise.all([...c.values()].map(e=>i(e))));if(r&&e.length>0){let t=e.reduce((e,t)=>(e[E(t,o)]=t,e),{});await w(()=>r(t))}e.forEach(e=>{e&&(r||w(()=>n(e[o],e)),l.set(E(e,o),e))})}return s.map(e=>e?l.get(E(e,o)):null)};var O=class extends o{innerError;message;constructor(e,t){super(),this.innerError=t,this.message=e}toString(){return`${this.message}: ${this.innerError}`}},k=class extends O{key;constructor(e,t,n){super(e,t),this.key=n}toString(){return`${this.message} (${this.key}): ${this.innerError}`}};const A=e=>{Object.keys(e).forEach(t=>{typeof e[t]==`function`&&(e[`${t}Async`]=c(e[t]),Object.defineProperty(e[`${t}Async`],`__isPromisified__`,{value:!0,configurable:!0,enumerable:!1,writable:!0}))})};A(a.RedisClient.prototype),A(a.Multi.prototype);const{env:j}=process,M=j.REDIS_HOST_NAME||`127.0.0.1`,N=j.REDIS_HOST_PORT||6379,P=j.AF_SERVICE_NAME,F=5e3,I=1e3,L=3600,R=P+`:`;if(!P)throw Error(`SERVICE_NAME cannot be null, please check your env.AF_SERVICE_NAME`);var z=class{client;locker;lockTimeout;lockDuration;locks={};baseTTL;lockRetries;keyPrefix=R;useLock;constructor(e){this.client=a.createClient({host:e.host||M,port:e.port||N}),this.locker=c(s(this.client,e.lockRetries??10)),this.lockTimeout=e.lockTimeout??F,this.lockDuration=e.lockDuration??I,this.baseTTL=e.ttl??L,this.useLock=!!e.useLock}async get(e){let t=R+e,n;try{n=await this.client.getAsync(t)}catch(e){throw new O(`Failed to get a value`,e)}if(this.useLock){let e;try{e=await this.lock(t)}catch(e){throw new k(`Failed to lock key`,e,t)}this.locks[t]=e}return JSON.parse(n)}async getMultiple(e){let t=e.map(e=>R+e),n;try{if(t.length===0)return[];n=await this.client.mgetAsync(t)}catch(e){throw new O(`Failed to get a value`,e)}return n.map(e=>JSON.parse(e))}async set(e,t){let n=R+e,r=parseInt(String(this.baseTTL*(Math.random()+1)),10);try{await this.client.setAsync(n,JSON.stringify(t),`EX`,r),this.locks[n]&&(await this.locks[n](),delete this.locks[n])}catch(e){throw new O(`Failed to set a key-value pair`,e)}}async setMultiple(e){if(typeof e!=`object`){let e=new O(`keyValues must be an object`,Error(`keyValues must be an object`));throw m.error(`keyValues must be an object`,{error:e}),e}if(e==null||Object.keys(e).length===0)return;let t=Object.entries(e).map(([e,t])=>[R+e,JSON.stringify(t)]),n=Math.trunc(this.baseTTL*(Math.random()+1));try{let e=this.client.multi(),r=e.msetAsync(...t.flat());return t.map(([t])=>e.expireAsync(t,n)),await e.exec(),r}catch(e){throw new O(`Failed to set multiple key-value pairs`,e)}}async remove(e){let t=R+e;try{this.locks[t]&&(await this.locks[t](),delete this.locks[t]),await this.client.delAsync(t)}catch(e){throw new O(`Failed to delete key ${t}`,e)}}async removeMultiple(e){let t=e.map(e=>R+e);try{await this.client.delAsync(t)}catch(e){throw new O(`Failed to delete multiple keys ${t.join(`|`)}`,e)}}getClient(){return this.client}lock(e){return Promise.race([this.locker(e,this.lockDuration),new Promise((e,t)=>setTimeout(()=>t(),this.lockTimeout))])}},B=z;const{AF_SERVICE_NAME:V}=process.env,H=`ormCache`,U=[`afterSave`,`afterUpdate`,`afterDestroy`],W=[`beforeBulkUpdate`,`beforeBulkDestroy`],G=(e,t)=>`${V}:${H}:${e}_${t}`,K=(e,t,n)=>`${V}:${H}:${e}_${t}_${n}_DEPENDENCIES`,q=(e,t)=>{let n=e.associations.filter(e=>t[e.alias]).map(n=>{let r=n.accessKey,i=[];return Array.isArray(t[n.alias])?(t[n.alias].forEach(t=>{i.push(K(e.name,n.name,t[r])),n.innerAssociation&&t[n.innerAssociation.alias]&&i.push(K(e.name,n.innerAssociation.name,t[n.innerAssociation.alias][n.innerAssociation.accessKey]))}),i):[K(e.name,n.name,t[n.alias][r])]});return n.reduce((e,t)=>e.concat(t),[])},J=(e,t,n)=>{let{transaction:r}=t;r?r.afterCommit(()=>n(e)):n(e)};var Y=class{constructor(e,t){this.ormInstance=e,this.debugMode=t}getModel(e){return this.ormInstance.models[e]}getModelDependencies(e){let{associations:t}=this.ormInstance.models[e];return[...Object.keys(t).map(e=>{let n=t[e],r={alias:n.as,name:n.target.name,accessKey:n.target.primaryKeyAttribute},{through:i}=n;if(i){let e=i.model;r.innerAssociation={alias:e.name,name:e.name,accessKey:e.primaryKeyAttribute}}return r})]}debug(e,t){this.debugMode&&m.info(`[ORM_CACHE Debug] ${e}`,t)}injectGetWithCacheFunction(e,t){let n=async n=>{let r=q(t,n),i=G(t.name,n.id);this.debug(`Adding dependencies`,{instanceKey:i,dependencyKeys:r});let a=e.getClient().multi(),o=c(a.exec).bind(a);return r.reduce((e,t)=>e.sadd(t,i),a),o()},r=this.getModel(t.name);r.findByPkCached=async(i,a,o)=>{let s=G(t.name,i),c=JSON.parse(await e.getClient().getAsync(s));return c?(c=this.getModel(t.name).build(c,{isNewRecord:!1,include:o.include}),this.debug(`Found cached value`,{value:c,id:i,cacheKey:s})):(this.debug(`Value not found in cache, looking in db`,{id:i,cacheKey:s}),c=await r.scope(a).findByPk(i,o),this.debug(`Value from DB`,{value:c||`not found`,cacheKey:s}),await Promise.all([e.getClient().setAsync(s,JSON.stringify(c)),c&&n(c)])),c}}addInvalidationHooks(e,t){let n=async n=>{let r=q(t,n),i=G(t.name,n.id);this.debug(`Removing dependencies`,{instance:n,instanceKey:i,dependencyKeys:r});let a=e.getClient().multi(),o=c(a.exec).bind(a);return r.map(e=>a.srem(e,i)),a.del(i),o()},r=async(n,r)=>{let i=await e.getClient().smembersAsync(K(t.name,n,r));this.debug(`Invalidating dependent instances`,{dependentInstancesKeys:i});let a=e.getClient().multi(),o=c(a.exec).bind(a),s=await Promise.all(i.map(async n=>{let r=JSON.parse(await e.getClient().getAsync(n));if(!r)return[];let i=q(t,r);return i.reduce((e,t)=>e.srem(t,n),a),a.del(n),i}));return this.debug(`Removing dependencies`,{dependentInstancesKeys:i,dependenciesToRemove:s}),o()},i=this.getModel(t.name);U.map(e=>i.addHook(e,(e,t)=>J(e,t,e=>n(e)))),W.map(e=>i.addHook(e,e=>{e.individualHook=!0})),t.associations=this.getModelDependencies(t.name),this.debug(`Adding Invalidations Hooks to ${t.name}'s associations`,{associations:t.associations}),t.associations.forEach(e=>{let t=this.getModel(e.name);if(U.forEach(n=>t.addHook(n,(t,n)=>J(t,n,t=>r(e.name,t[e.accessKey])))),W.forEach(e=>t.addHook(e,e=>{e.individualHook=!0})),e.innerAssociation){let t=this.getModel(e.innerAssociation.name);U.forEach(n=>t.addHook(n,(t,n)=>J(t,n,t=>r(e.innerAssociation.name,t[e.innerAssociation.accessKey])))),W.map(e=>t.addHook(e,e=>{e.individualHook=!0}))}})}},X=class extends Error{};let Z=function(e){return e.SEQUELIZE=`sequelize`,e}({});const Q=e=>{switch(e.type){case Z.SEQUELIZE:return new Y(e.ormInstance,e.debug);default:throw new X(`ORM type ${e.type} is unsupported at the moment`)}},$=e=>{let{models:t}=e;m.info(`Starting ORM Cache`,{options:e});let n=Q(e),r=new B({host:process.env.REDIS_HOST,port:Number.parseInt(process.env.REDIS_PORT,10)});t.map(e=>{n.addInvalidationHooks(r,e),n.injectGetWithCacheFunction(r,e)})};export{$ as ORMCache,Z as ORMTypes,B as RedisCache,D as getMultipleWithCache,x as getNewLRU,T as getWithCacheSupport};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache.ts","../src/locking.ts","../src/logger.ts","../src/redis/index.ts","../src/redis/errors.ts","../src/promise-utils.ts","../src/orm-cache/sequelize-adapter.ts","../src/orm-cache/errors.ts","../src/orm-cache/index.ts"],"names":["CACHE_LOCK_TIMEOUT_MILIS","LOCK_TIMEOUT_MESSAGE","wrapWithMutex","__name","mutex","funcToRun","release","acquire","getMutex","withTimeout","Mutex","Error","logger","CustomLogger","logger_default","dotenv","config","DEFAULT_CACHE_SIZE","MAX_SIZE","MUTEX_MAP","getOptions","lifeTimeInSec","size","max","Math","min","maxAge","process","env","NODE_ENV","getMutexByCacheKey","key","deleteMutexByCacheKey","getNewLRU","LRU","IN_LOCAL_TEST","IS_IN_MATMON_TESTING","IS_IN_SERVICE_TEST","tryToSetInCache","callback","e","error","getWithCacheSupport","cacheKey","cacheGet","cacheSet","fetching","skipCache","res","valueToReturn","getIdField","query","idField","getMultipleWithCache","getFromCache","multiGetterFromCache","setInCache","setMultiInCache","getter","multiGetter","queries","queriesMap","Map","filter","Boolean","map","resultMap","valuesToPullFromCache","values","Promise","all","forEach","value","delete","set","valuesFromGetter","id","length","setCacheObject","reduce","acc","get","RedisCacheError","RedisError","innerError","message","constructor","msg","err","toString","RedisLockError","promisifyAll","obj","Object","keys","promisify","defineProperty","configurable","enumerable","writable","redis","RedisClient","prototype","Multi","HOST","REDIS_HOST_NAME","PORT","REDIS_HOST_PORT","SERVICE_NAME","AF_SERVICE_NAME","DEFAULT_LOCK_TIMEOUT","DEFAULT_LOCK_DURATION","DEFAULT_BASE_TTL","KEY_PREFIX","RedisCache","client","locker","lockTimeout","lockDuration","locks","baseTTL","lockRetries","keyPrefix","useLock","options","createClient","host","port","redisLock","ttl","keyWithPrefix","getAsync","lock","JSON","parse","getMultiple","keysWithPrefix","mgetAsync","parseInt","String","random","setAsync","stringify","setMultiple","keyValues","keyValuesWithPrefix","entries","trunc","multi","setPromise","msetAsync","flat","expireAsync","exec","remove","delAsync","removeMultiple","join","getClient","race","_resolve","reject","setTimeout","redis_default","ORM_CACHE_PREFIX","INVALIDATION_HOOKS","BULK_HOOKS","generateInstanceKey","name","generateDependencyKey","modelName","associationName","associationId","getInstanceDependencyKeys","modelOptions","instance","associations","associationOptions","alias","accessKey","depKeys","Array","isArray","associationInstance","push","innerAssociation","flattenArray","array","concat","handleTransactionHook","func","transaction","afterCommit","SequelizeAdapter","ormInstance","debugMode","sequelize","debug","getModel","models","getModelDependencies","association","sequelizeAssociation","as","target","primaryKeyAttribute","through","relationModel","model","payload","info","injectGetWithCacheFunction","cache","addDependencies","dependencyKeys","instanceKey","addDependenciesMulti","addDependenciesMultiAsync","bind","sadd","findByPkCached","scopes","build","isNewRecord","include","scope","findByPk","addInvalidationHooks","invalidateModelInstance","removeMulti","removeMultiAsync","srem","del","invalidateModelInstanceByAssociation","dependentInstancesKeys","smembersAsync","dependenciesToRemove","hook","addHook","individualHook","associationModel","innerAssociationModel","innerAssociationInstance","UnsupportedOrmTypeError","ORMTypes","ORMInstanceFactory","type","ORMCache","adapter","REDIS_HOST","REDIS_PORT"],"mappings":"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","file":"index.js","sourcesContent":["import LRU from 'lru-cache';\n\nimport * as locking from './locking';\nimport dotenv from 'dotenv';\nimport type { MutexInterface } from 'async-mutex';\nimport logger from './logger';\n\ndotenv.config();\n\nconst DEFAULT_CACHE_SIZE = 300;\nconst MAX_SIZE = 100000;\nconst MUTEX_MAP = {} as Record<keyof any, undefined | MutexInterface>;\n\ninterface Options {\n lifeTimeInSec: number;\n size?: number;\n}\n\nconst getOptions = <K, V>({\n lifeTimeInSec,\n size = DEFAULT_CACHE_SIZE,\n}: Options): LRU.Options<K, V> => ({\n max: Math.min(size, MAX_SIZE),\n maxAge: process.env.NODE_ENV !== 'test' ? 1000 * lifeTimeInSec : 0,\n});\n\nconst getMutexByCacheKey = (key: keyof any) => {\n MUTEX_MAP[key] ??= locking.getMutex();\n return MUTEX_MAP[key];\n};\n\nconst deleteMutexByCacheKey = (key: keyof any) => {\n if (MUTEX_MAP[key]) {\n delete MUTEX_MAP[key];\n }\n};\n\nexport const getNewLRU = <K = unknown, V = unknown>(lifeTimeInSec: Options['lifeTimeInSec'], size?: Options['size']) => new LRU<K, V>(getOptions<K, V>({\n lifeTimeInSec,\n size,\n}));\n\ninterface GetWithCacheOptions<V = unknown> {\n cacheKey: string;\n cacheGet: () => Promise<V>;\n cacheSet: (value: V) => Promise<void>;\n fetching: () => Promise<V>;\n skipCache?: boolean;\n}\n\nconst IN_LOCAL_TEST = process.env.IS_IN_MATMON_TESTING === 'true';\nconst IS_IN_SERVICE_TEST = process.env.NODE_ENV === 'test' && !IN_LOCAL_TEST;\n\nconst tryToSetInCache = async (callback): Promise<void> => {\n try {\n await callback();\n } catch (e) {\n logger.error('Failed to set in cache', e);\n }\n};\n\nexport const getWithCacheSupport = async <V = unknown>({\n cacheKey,\n cacheGet,\n cacheSet,\n fetching,\n skipCache,\n}: GetWithCacheOptions<V>) => {\n if (skipCache || IS_IN_SERVICE_TEST) {\n const res = await fetching();\n await tryToSetInCache(() => cacheSet(res));\n return res;\n }\n let valueToReturn: Awaited<V> | null = null;\n try {\n await locking.wrapWithMutex(getMutexByCacheKey(cacheKey), async () => {\n valueToReturn = await cacheGet();\n if (!valueToReturn) {\n valueToReturn = await fetching();\n await tryToSetInCache(() => cacheSet(valueToReturn!));\n } else {\n // logger.info('get value from cache');\n }\n deleteMutexByCacheKey(cacheKey);\n });\n // retry without locking if failed\n } catch {\n valueToReturn = await fetching();\n await tryToSetInCache(() => cacheSet(valueToReturn!));\n deleteMutexByCacheKey(cacheKey);\n }\n return valueToReturn;\n};\n\n\nconst getIdField = (query: string | object, idField: keyof any): string => {\n if (typeof query === 'string') {\n return query;\n }\n return query[idField];\n};\n\ninterface GetMultipleWithCacheOptions<V = unknown> {\n getFromCache?: (query: any) => Promise<V>;\n multiGetterFromCache?: (queries: any[]) => Promise<V[]>;\n setInCache: (key: string, value: V) => Promise<void>;\n getter?: (query: any) => Promise<V>;\n multiGetter?: (queries: any[]) => Promise<V[]>;\n setMultiInCache?: (keyValues: Record<string, object>) => Promise<void>;\n idField?: string;\n}\n\nexport const getMultipleWithCache = <V = unknown>({\n getFromCache,\n multiGetterFromCache,\n setInCache,\n setMultiInCache,\n getter,\n multiGetter,\n idField = 'id',\n}: GetMultipleWithCacheOptions<V>) => async (queries: any[]) => {\n const queriesMap = new Map(queries.filter(Boolean).map(query => [getIdField(query, idField), query]));\n const resultMap = new Map<string, V>();\n\n const valuesToPullFromCache = [...queriesMap.values()];\n\n const valuesFromCache = await (\n multiGetterFromCache?.(valuesToPullFromCache) // Use multiGetterFromCache if it's provided\n ?? Promise.all(valuesToPullFromCache.map(query => getFromCache!(query))) // Otherwise, iterate over the queries with getFromCache\n );\n\n\n valuesFromCache.filter(Boolean).forEach((value) => {\n queriesMap.delete(getIdField(value as object, idField));\n resultMap.set(getIdField(value as object, idField), value);\n });\n\n if (queriesMap.size > 0) {\n const valuesFromGetter = await (\n multiGetter?.([...queriesMap.values()]) // Use multiGetter if it's provided\n ?? Promise.all([...queriesMap.values()].map(id => getter!(id))) // Otherwise, iterate over the queries with getter\n );\n\n if (setMultiInCache && valuesFromGetter.length > 0) {\n const setCacheObject = valuesFromGetter.reduce((acc, value) => {\n acc[getIdField(value as object, idField)] = value;\n return acc;\n }, {});\n await tryToSetInCache(() => setMultiInCache(setCacheObject));\n }\n\n valuesFromGetter.forEach((value) => {\n if (!value) {\n return;\n }\n if (!setMultiInCache) {\n void tryToSetInCache(() => setInCache(value[idField], value));\n }\n resultMap.set(getIdField(value as object, idField), value);\n });\n }\n\n return queries.map((query) => {\n if (!query) {\n return null;\n }\n return resultMap.get(getIdField(query, idField));\n });\n};\n","import { Mutex, type MutexInterface, withTimeout } from 'async-mutex';\n\nconst CACHE_LOCK_TIMEOUT_MILIS = 3000;\nconst LOCK_TIMEOUT_MESSAGE = 'mutex - locking timeout';\n\nexport const wrapWithMutex = async (mutex: MutexInterface, funcToRun: () => PromiseLike<void>) => {\n const release = await mutex.acquire();\n try {\n await funcToRun();\n } finally {\n release();\n }\n};\n\nexport const getMutex = (): MutexInterface => withTimeout(new Mutex(), CACHE_LOCK_TIMEOUT_MILIS, new Error(LOCK_TIMEOUT_MESSAGE));\n","import CustomLogger from '@autofleet/logger';\n\nconst logger = CustomLogger();\n\nexport default logger;\n","import redis from 'redis';\nimport redisLock from 'redis-lock';\nimport { promisify } from 'util';\nimport { RedisCacheError, RedisLockError } from './errors';\nimport logger from '../logger';\nimport { promisifyAll } from '../promise-utils';\n\npromisifyAll(redis.RedisClient.prototype);\npromisifyAll(redis.Multi.prototype);\n\nconst { env } = process;\n\nconst HOST = env.REDIS_HOST_NAME || '127.0.0.1';\nconst PORT = env.REDIS_HOST_PORT || 6379;\nconst SERVICE_NAME = env.AF_SERVICE_NAME;\nconst DEFAULT_LOCK_TIMEOUT = 5000;\nconst DEFAULT_LOCK_DURATION = 1000;\nconst DEFAULT_BASE_TTL = 3600;\nconst KEY_PREFIX = SERVICE_NAME + ':';\n\nif (!SERVICE_NAME) {\n throw new Error('SERVICE_NAME cannot be null, please check your env.AF_SERVICE_NAME');\n}\n\nclass RedisCache {\n // node redis client instance.\n private client: any;\n\n // A redis-lock instance.\n private locker: any;\n\n // The time that the cache will wait until a lock\n // will be considered as failed (in milliseconds).\n private lockTimeout: number;\n\n // The time that a key will be locked.\n private lockDuration: number;\n\n // A dictionary of key and its lock.\n locks: any;\n\n // The time that a key-value pair will exist in redis.\n // To this base time will be added between 1 to 2 milliseconds.\n private baseTTL: number;\n\n // The number of retries that we will try to lock a key in case of failure.\n private lockRetries: number;\n\n keyPrefix: string;\n\n useLock: boolean;\n\n constructor(options) {\n this.client = redis.createClient({\n host: options.host || HOST,\n port: options.port || PORT,\n });\n this.locker = promisify(redisLock(this.client, options.lockRetries ?? 10));\n this.lockTimeout = options.lockTimeout ?? DEFAULT_LOCK_TIMEOUT;\n this.lockDuration = options.lockDuration ?? DEFAULT_LOCK_DURATION;\n this.baseTTL = options.ttl ?? DEFAULT_BASE_TTL;\n this.locks = {};\n this.useLock = !!options.useLock;\n this.keyPrefix = KEY_PREFIX;\n }\n\n async get(key) {\n const keyWithPrefix = KEY_PREFIX + key;\n\n let value;\n try {\n // Try to get the value from redis.\n value = await this.client.getAsync(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to get a value', err);\n }\n\n if (this.useLock) {\n let lock;\n try {\n // Try to lock the key.\n lock = await this.lock(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisLockError('Failed to lock key', err, keyWithPrefix);\n }\n\n // If the lock did not fail, add it to a locks dictionary.\n this.locks[keyWithPrefix] = lock;\n }\n\n return JSON.parse(value);\n }\n\n async getMultiple(keys) {\n const keysWithPrefix = keys.map(key => KEY_PREFIX + key);\n let values;\n try {\n if (keysWithPrefix.length === 0) {\n return [];\n }\n // Try to get the value from redis.\n values = await this.client.mgetAsync(keysWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to get a value', err);\n }\n return values.map(value => JSON.parse(value));\n }\n\n async set(key, value) {\n const keyWithPrefix = KEY_PREFIX + key;\n const ttl = parseInt(String(this.baseTTL * (Math.random() + 1)), 10);\n try {\n await this.client.setAsync(keyWithPrefix, JSON.stringify(value), 'EX', ttl);\n if (this.locks[keyWithPrefix]) {\n await this.locks[keyWithPrefix]();\n delete this.locks[keyWithPrefix];\n }\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to set a key-value pair', err);\n }\n }\n\n async setMultiple(keyValues: Record<string, any>) {\n if (typeof keyValues !== 'object') {\n const error = new RedisCacheError('keyValues must be an object', new Error('keyValues must be an object'));\n logger.error('keyValues must be an object', { error });\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw error;\n }\n\n if (keyValues === null || keyValues === undefined || Object.keys(keyValues).length === 0) {\n return undefined;\n }\n\n const keyValuesWithPrefix = Object.entries(keyValues).map(([key, value]) => [KEY_PREFIX + key, JSON.stringify(value)]);\n const ttl = Math.trunc(this.baseTTL * (Math.random() + 1));\n try {\n const multi = this.client.multi();\n const setPromise = multi.msetAsync(...keyValuesWithPrefix.flat());\n keyValuesWithPrefix.map(([key]) => multi.expireAsync(key, ttl));\n await multi.exec();\n return setPromise;\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to set multiple key-value pairs', err);\n }\n }\n\n async remove(key) {\n const keyWithPrefix = KEY_PREFIX + key;\n try {\n if (this.locks[keyWithPrefix]) {\n await this.locks[keyWithPrefix]();\n delete this.locks[keyWithPrefix];\n }\n\n await this.client.delAsync(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError(`Failed to delete key ${keyWithPrefix}`, err);\n }\n }\n\n async removeMultiple(keys) {\n const keysWithPrefix = keys.map(key => KEY_PREFIX + key);\n try {\n await this.client.delAsync(keysWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError(`Failed to delete multiple keys ${keysWithPrefix.join('|')}`, err);\n }\n }\n\n getClient() {\n return this.client;\n }\n\n private lock(key) {\n return Promise.race([\n this.locker(key, this.lockDuration),\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n new Promise((_resolve, reject) => setTimeout(() => reject(), this.lockTimeout)),\n ]);\n }\n}\n\nexport default RedisCache;\n","import { RedisError } from 'redis';\n\nclass RedisCacheError extends RedisError {\n innerError: any;\n message: string;\n constructor(msg: string, err) {\n super();\n this.innerError = err;\n this.message = msg;\n }\n\n toString() {\n return `${this.message}: ${this.innerError}`;\n }\n}\n\nclass RedisLockError extends RedisCacheError {\n key: string;\n constructor(msg: string, err, key: string) {\n super(msg, err);\n this.key = key;\n }\n\n toString() {\n return `${this.message} (${this.key}): ${this.innerError}`;\n }\n}\n\nexport {\n RedisCacheError,\n RedisLockError,\n};\n","import { promisify } from 'util';\n\nexport const promisifyAll = (obj) => {\n Object.keys(obj).forEach((key) => {\n if (typeof obj[key] === 'function') {\n obj[`${key}Async`] = promisify(obj[key]);\n\n // To support the `isPromisified` check in `bluebird`, we need to set the `__isPromisified__` property to `true`.\n Object.defineProperty(obj[`${key}Async`], '__isPromisified__', {\n value: true,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n });\n};\n","import type { Sequelize } from 'sequelize';\nimport type { Adapter, AssociationOptions, ModelOptions } from './adapter';\nimport type RedisCache from '../redis';\nimport logger from '../logger';\nimport { promisify } from 'util';\n\nconst { AF_SERVICE_NAME } = process.env;\nconst ORM_CACHE_PREFIX = 'ormCache';\nconst INVALIDATION_HOOKS = ['afterSave', 'afterUpdate', 'afterDestroy'];\nconst BULK_HOOKS = ['beforeBulkUpdate', 'beforeBulkDestroy'];\n\nconst generateInstanceKey = (name: string, id: string): string =>\n `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${name}_${id}`;\n\nconst generateDependencyKey = (modelName: string, associationName: string, associationId: string): string =>\n `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${modelName}_${associationName}_${associationId}_DEPENDENCIES`;\n\nconst getInstanceDependencyKeys = (modelOptions: ModelOptions, instance): string[] => {\n const keys = modelOptions.associations!\n .filter((associationOptions: AssociationOptions) => instance[associationOptions.alias])\n .map((associationOptions: AssociationOptions): string[] => {\n const accessKey = associationOptions.accessKey!;\n const depKeys: string[] = [];\n if (Array.isArray(instance[associationOptions.alias])) {\n instance[associationOptions.alias].forEach((associationInstance) => {\n depKeys.push(generateDependencyKey(\n modelOptions.name,\n associationOptions.name,\n associationInstance[accessKey],\n ));\n if (associationOptions.innerAssociation && associationInstance[associationOptions.innerAssociation.alias]) {\n depKeys.push(generateDependencyKey(\n modelOptions.name,\n associationOptions.innerAssociation.name,\n associationInstance[associationOptions.innerAssociation.alias][associationOptions.innerAssociation.accessKey!],\n ));\n }\n });\n return depKeys;\n }\n return [\n generateDependencyKey(\n modelOptions.name,\n associationOptions.name,\n instance[associationOptions.alias][accessKey],\n ),\n ];\n });\n return keys.reduce((flattenArray, array) => flattenArray.concat(array), []);\n};\n\nconst handleTransactionHook = (instance, options, func) => {\n const { transaction } = options;\n if (transaction) {\n transaction.afterCommit(() => func(instance));\n } else {\n func(instance);\n }\n};\n\nexport default class SequelizeAdapter implements Adapter {\n ormInstance: Sequelize;\n debugMode: boolean;\n\n constructor(sequelize: Sequelize, debug) {\n this.ormInstance = sequelize;\n this.debugMode = debug;\n }\n\n getModel(modelName: string): any {\n return this.ormInstance.models[modelName];\n }\n\n getModelDependencies(modelName: string): AssociationOptions[] {\n const { associations } = this.ormInstance.models[modelName];\n return [\n ...Object.keys(associations).map((association) => {\n const sequelizeAssociation: any = associations[association];\n const associationOptions: AssociationOptions = {\n alias: sequelizeAssociation.as,\n name: sequelizeAssociation.target.name,\n accessKey: sequelizeAssociation.target.primaryKeyAttribute,\n };\n\n if (sequelizeAssociation.through) {\n const relationModel = sequelizeAssociation.through.model;\n associationOptions.innerAssociation = {\n alias: relationModel.name,\n name: relationModel.name,\n accessKey: relationModel.primaryKeyAttribute,\n };\n }\n\n return associationOptions;\n }),\n ];\n }\n\n debug(message, payload) {\n if (this.debugMode) {\n logger.info(`[ORM_CACHE Debug] ${message}`, payload);\n }\n }\n\n injectGetWithCacheFunction(cache: RedisCache, modelOptions: ModelOptions): void {\n const addDependencies = async (instance) => {\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n const instanceKey = generateInstanceKey(modelOptions.name, instance.id);\n this.debug('Adding dependencies', { instanceKey, dependencyKeys });\n const addDependenciesMulti = cache.getClient().multi();\n const addDependenciesMultiAsync = promisify(addDependenciesMulti.exec).bind(addDependenciesMulti);\n dependencyKeys.reduce((multi, key) => multi.sadd(key, instanceKey), addDependenciesMulti);\n return addDependenciesMultiAsync();\n };\n\n const model = this.getModel(modelOptions.name);\n model.findByPkCached = async (id: string, scopes: string[], options: any): Promise<any> => {\n const cacheKey = generateInstanceKey(modelOptions.name, id);\n let value = JSON.parse(await cache.getClient().getAsync(cacheKey));\n if (!value) {\n this.debug('Value not found in cache, looking in db', { id, cacheKey });\n value = await model.scope(scopes).findByPk(id, options);\n this.debug('Value from DB', { value: value || 'not found', cacheKey });\n await Promise.all([\n cache.getClient().setAsync(cacheKey, JSON.stringify(value)),\n value && addDependencies(value),\n ]);\n } else {\n value = this.getModel(modelOptions.name).build(value, { isNewRecord: false, include: options.include });\n this.debug('Found cached value', { value, id, cacheKey });\n }\n return value;\n };\n }\n\n addInvalidationHooks(cache: RedisCache, modelOptions: ModelOptions): void {\n const invalidateModelInstance = async (instance) => {\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n const instanceKey = generateInstanceKey(modelOptions.name, instance.id);\n this.debug('Removing dependencies', { instance, instanceKey, dependencyKeys });\n const removeMulti = cache.getClient().multi();\n const removeMultiAsync = promisify(removeMulti.exec).bind(removeMulti);\n dependencyKeys.map(key => removeMulti.srem(key, instanceKey));\n removeMulti.del(instanceKey);\n return removeMultiAsync();\n };\n\n const invalidateModelInstanceByAssociation = async (association, associationId) => {\n const dependentInstancesKeys = await cache.getClient().smembersAsync(generateDependencyKey(\n modelOptions.name,\n association,\n associationId,\n ));\n this.debug('Invalidating dependent instances', { dependentInstancesKeys });\n const removeMulti = cache.getClient().multi();\n const removeMultiAsync = promisify(removeMulti.exec).bind(removeMulti);\n const dependenciesToRemove = await Promise.all(dependentInstancesKeys.map(async (instanceKey) => {\n const instance = JSON.parse(await cache.getClient().getAsync(instanceKey));\n if (!instance) {\n return [];\n }\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n dependencyKeys.reduce((multi, key) => multi.srem(key, instanceKey), removeMulti);\n removeMulti.del(instanceKey);\n return dependencyKeys;\n }));\n this.debug('Removing dependencies', { dependentInstancesKeys, dependenciesToRemove });\n return removeMultiAsync();\n };\n\n const model = this.getModel(modelOptions.name);\n INVALIDATION_HOOKS.map(hook => model.addHook(hook, (instance, options) =>\n handleTransactionHook(instance, options, instance => invalidateModelInstance(instance))));\n BULK_HOOKS.map(hook => model.addHook(hook, options => options.individualHook = true));\n\n modelOptions.associations = this.getModelDependencies(modelOptions.name);\n this.debug(`Adding Invalidations Hooks to ${modelOptions.name}'s associations`, { associations: modelOptions.associations });\n modelOptions.associations.forEach((associationOptions) => {\n const associationModel = this.getModel(associationOptions.name);\n INVALIDATION_HOOKS.forEach(hook => associationModel.addHook(hook, (instance, options) =>\n handleTransactionHook(\n instance,\n options,\n associationInstance => invalidateModelInstanceByAssociation(\n associationOptions.name,\n associationInstance[associationOptions.accessKey!],\n ),\n ),\n ));\n BULK_HOOKS.forEach(hook => associationModel.addHook(hook, options => options.individualHook = true));\n\n if (associationOptions.innerAssociation) {\n const innerAssociationModel = this.getModel(associationOptions.innerAssociation.name);\n INVALIDATION_HOOKS.forEach(hook => innerAssociationModel.addHook(hook, (instance, options) =>\n handleTransactionHook(\n instance,\n options,\n innerAssociationInstance => invalidateModelInstanceByAssociation(\n associationOptions.innerAssociation!.name,\n innerAssociationInstance[associationOptions.innerAssociation!.accessKey!],\n ),\n ),\n ));\n BULK_HOOKS.map(hook => innerAssociationModel.addHook(hook, options => options.individualHook = true));\n }\n });\n }\n}\n","export class UnsupportedOrmTypeError extends Error {}\n","import type { Adapter, ModelOptions } from './adapter';\nimport SequelizeAdapter from './sequelize-adapter';\nimport { UnsupportedOrmTypeError } from './errors';\nimport RedisCache from '../redis';\nimport logger from '../logger';\n\nexport enum ORMTypes {\n SEQUELIZE = 'sequelize',\n}\n\ninterface ORMCacheOptions {\n type: ORMTypes;\n models: ModelOptions[];\n ormInstance: any;\n debug: boolean;\n}\n\nconst ORMInstanceFactory = (options: ORMCacheOptions): Adapter => {\n switch (options.type) {\n case ORMTypes.SEQUELIZE: {\n return new SequelizeAdapter(options.ormInstance, options.debug);\n }\n default: {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new UnsupportedOrmTypeError(`ORM type ${options.type} is unsupported at the moment`);\n }\n }\n};\n\nexport const ORMCache = (options: ORMCacheOptions): void => {\n const { models } = options;\n logger.info('Starting ORM Cache', { options });\n const adapter = ORMInstanceFactory(options);\n const cache = new RedisCache({\n host: process.env.REDIS_HOST,\n port: process.env.REDIS_PORT,\n });\n // eslint-disable-next-line array-callback-return\n models.map((modelOptions): void => {\n adapter.addInvalidationHooks(cache, modelOptions);\n adapter.injectGetWithCacheFunction(cache, modelOptions);\n });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["mutex: MutexInterface","funcToRun: () => PromiseLike<void>","key: keyof any","lifeTimeInSec: Options['lifeTimeInSec']","size?: Options['size']","callback: () => void | PromiseLike<void>","valueToReturn: Awaited<V> | null","query: string | object","idField: keyof any","msg: string","err: any","key: string","obj: object","options: RedisCacheOptions","key: string","keys: string[]","value: T","keyValues: Record<string, T>","name: string","id: string","modelName: string","associationName: string","associationId: string","modelOptions: ModelOptions","associationOptions: AssociationOptions","depKeys: string[]","ormInstance: Sequelize","debugMode: boolean","message: string","payload?: unknown","cache: RedisCache","scopes: string[]","options: Omit<NonNullFindOptions<Attributes<M>>, 'where'>","instance","options: ORMCacheOptions","RedisCache"],"sources":["../src/locking.ts","../src/logger.ts","../src/cache.ts","../src/redis/errors.ts","../src/promise-utils.ts","../src/redis/index.ts","../src/orm-cache/sequelize-adapter.ts","../src/orm-cache/errors.ts","../src/orm-cache/index.ts"],"sourcesContent":["import { Mutex, type MutexInterface, withTimeout } from 'async-mutex';\n\nconst CACHE_LOCK_TIMEOUT_MILIS = 3000;\nconst LOCK_TIMEOUT_MESSAGE = 'mutex - locking timeout';\n\nexport const wrapWithMutex = async (mutex: MutexInterface, funcToRun: () => PromiseLike<void>) => {\n const release = await mutex.acquire();\n try {\n await funcToRun();\n } finally {\n release();\n }\n};\n\nexport const getMutex = (): MutexInterface => withTimeout(new Mutex(), CACHE_LOCK_TIMEOUT_MILIS, new Error(LOCK_TIMEOUT_MESSAGE));\n","import CustomLogger from '@autofleet/logger';\n\nconst logger = CustomLogger();\n\nexport default logger;\n","import LRU from 'lru-cache';\n\nimport * as locking from './locking';\nimport dotenv from 'dotenv';\nimport type { MutexInterface } from 'async-mutex';\nimport logger from './logger';\n\ndotenv.config();\n\nconst DEFAULT_CACHE_SIZE = 300;\nconst MAX_SIZE = 100000;\nconst MUTEX_MAP = {} as Record<keyof any, undefined | MutexInterface>;\n\ninterface Options {\n lifeTimeInSec: number;\n size?: number;\n}\n\nconst getOptions = <K, V>({\n lifeTimeInSec,\n size = DEFAULT_CACHE_SIZE,\n}: Options): LRU.Options<K, V> => ({\n max: Math.min(size, MAX_SIZE),\n maxAge: process.env.NODE_ENV !== 'test' ? 1000 * lifeTimeInSec : 0,\n});\n\nconst getMutexByCacheKey = (key: keyof any): MutexInterface => {\n MUTEX_MAP[key] ??= locking.getMutex();\n return MUTEX_MAP[key];\n};\n\nconst deleteMutexByCacheKey = (key: keyof any): void => {\n if (MUTEX_MAP[key]) {\n delete MUTEX_MAP[key];\n }\n};\n\nexport const getNewLRU = <K = unknown, V = unknown>(lifeTimeInSec: Options['lifeTimeInSec'], size?: Options['size']): LRU<K, V> => new LRU<K, V>(getOptions<K, V>({\n lifeTimeInSec,\n size,\n}));\n\ninterface GetWithCacheOptions<V = unknown> {\n cacheKey: string;\n cacheGet: () => Promise<V>;\n cacheSet: (value: V) => Promise<void>;\n fetching: () => Promise<V>;\n skipCache?: boolean;\n}\n\nconst IN_LOCAL_TEST = process.env.IS_IN_MATMON_TESTING === 'true';\nconst IS_IN_SERVICE_TEST = process.env.NODE_ENV === 'test' && !IN_LOCAL_TEST;\n\nconst tryToSetInCache = async (callback: () => void | PromiseLike<void>): Promise<void> => {\n try {\n await callback();\n } catch (e) {\n logger.error('Failed to set in cache', e);\n }\n};\n\nexport const getWithCacheSupport = async <V = unknown>({\n cacheKey,\n cacheGet,\n cacheSet,\n fetching,\n skipCache,\n}: GetWithCacheOptions<V>): Promise<V> => {\n if (skipCache || IS_IN_SERVICE_TEST) {\n const res = await fetching();\n await tryToSetInCache(() => cacheSet(res));\n return res;\n }\n let valueToReturn: Awaited<V> | null = null;\n try {\n await locking.wrapWithMutex(getMutexByCacheKey(cacheKey), async () => {\n valueToReturn = await cacheGet();\n if (!valueToReturn) {\n valueToReturn = await fetching();\n await tryToSetInCache(() => cacheSet(valueToReturn!));\n } else {\n // logger.info('get value from cache');\n }\n deleteMutexByCacheKey(cacheKey);\n });\n // retry without locking if failed\n } catch {\n valueToReturn = await fetching();\n await tryToSetInCache(() => cacheSet(valueToReturn!));\n deleteMutexByCacheKey(cacheKey);\n }\n return valueToReturn!;\n};\n\n\nconst getIdField = (query: string | object, idField: keyof any): string => {\n if (typeof query === 'string') {\n return query;\n }\n return query[idField];\n};\n\ninterface GetMultipleWithCacheOptions<V = unknown> {\n getFromCache?: (query: any) => Promise<V>;\n multiGetterFromCache?: (queries: any[]) => Promise<V[]>;\n setInCache: (key: string, value: V) => Promise<void>;\n getter?: (query: any) => Promise<V>;\n multiGetter?: (queries: any[]) => Promise<V[]>;\n setMultiInCache?: (keyValues: Record<string, object>) => Promise<void>;\n idField?: string;\n}\n\nexport const getMultipleWithCache = <V = unknown>({\n getFromCache,\n multiGetterFromCache,\n setInCache,\n setMultiInCache,\n getter,\n multiGetter,\n idField = 'id',\n}: GetMultipleWithCacheOptions<V>): (queries: any[]) => Promise<(V | null | undefined)[]> => async (queries) => {\n const queriesMap = new Map(queries.filter(Boolean).map(query => [getIdField(query, idField), query]));\n const resultMap = new Map<string, V>();\n\n const valuesToPullFromCache = [...queriesMap.values()];\n\n const valuesFromCache = await (\n multiGetterFromCache?.(valuesToPullFromCache) // Use multiGetterFromCache if it's provided\n ?? Promise.all(valuesToPullFromCache.map(query => getFromCache!(query))) // Otherwise, iterate over the queries with getFromCache\n );\n\n\n valuesFromCache.filter(Boolean).forEach((value) => {\n queriesMap.delete(getIdField(value as object, idField));\n resultMap.set(getIdField(value as object, idField), value);\n });\n\n if (queriesMap.size > 0) {\n const valuesFromGetter = await (\n multiGetter?.([...queriesMap.values()]) // Use multiGetter if it's provided\n ?? Promise.all([...queriesMap.values()].map(id => getter!(id))) // Otherwise, iterate over the queries with getter\n );\n\n if (setMultiInCache && valuesFromGetter.length > 0) {\n const setCacheObject = valuesFromGetter.reduce((acc, value) => {\n acc[getIdField(value as object, idField)] = value;\n return acc;\n }, {});\n await tryToSetInCache(() => setMultiInCache(setCacheObject));\n }\n\n valuesFromGetter.forEach((value) => {\n if (!value) {\n return;\n }\n if (!setMultiInCache) {\n void tryToSetInCache(() => setInCache(value[idField], value));\n }\n resultMap.set(getIdField(value as object, idField), value);\n });\n }\n\n return queries.map((query) => {\n if (!query) {\n return null;\n }\n return resultMap.get(getIdField(query, idField));\n });\n};\n","import { RedisError } from 'redis';\n\nclass RedisCacheError extends RedisError {\n innerError: any;\n message: string;\n constructor(msg: string, err: any) {\n super();\n this.innerError = err;\n this.message = msg;\n }\n\n toString(): string {\n return `${this.message}: ${this.innerError}`;\n }\n}\n\nclass RedisLockError extends RedisCacheError {\n key: string;\n constructor(msg: string, err: any, key: string) {\n super(msg, err);\n this.key = key;\n }\n\n toString(): string {\n return `${this.message} (${this.key}): ${this.innerError}`;\n }\n}\n\nexport {\n RedisCacheError,\n RedisLockError,\n};\n","import { promisify } from 'util';\n\n\nexport const promisifyAll = (obj: object) => {\n Object.keys(obj).forEach((key) => {\n if (typeof obj[key] === 'function') {\n obj[`${key}Async`] = promisify(obj[key]);\n\n // To support the `isPromisified` check in `bluebird`, we need to set the `__isPromisified__` property to `true`.\n Object.defineProperty(obj[`${key}Async`], '__isPromisified__', {\n value: true,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n });\n};\n","import redis from 'redis';\nimport redisLock from 'redis-lock';\nimport { promisify } from 'util';\nimport { RedisCacheError, RedisLockError } from './errors';\nimport logger from '../logger';\nimport { promisifyAll } from '../promise-utils';\n\npromisifyAll(redis.RedisClient.prototype);\npromisifyAll(redis.Multi.prototype);\n\nconst { env } = process;\n\nconst HOST = env.REDIS_HOST_NAME || '127.0.0.1';\nconst PORT = env.REDIS_HOST_PORT || 6379;\nconst SERVICE_NAME = env.AF_SERVICE_NAME;\nconst DEFAULT_LOCK_TIMEOUT = 5000;\nconst DEFAULT_LOCK_DURATION = 1000;\nconst DEFAULT_BASE_TTL = 3600;\nconst KEY_PREFIX = SERVICE_NAME + ':';\n\nif (!SERVICE_NAME) {\n throw new Error('SERVICE_NAME cannot be null, please check your env.AF_SERVICE_NAME');\n}\n\ninterface RedisCacheOptions {\n host?: string;\n port?: number;\n lockRetries?: number;\n lockTimeout?: number;\n lockDuration?: number;\n ttl?: number;\n useLock?: boolean;\n}\n\nclass RedisCache {\n // node redis client instance.\n private client: any;\n\n // A redis-lock instance.\n private locker: (key: string, duration: number) => Promise<() => Promise<void>>;\n\n // The time that the cache will wait until a lock\n // will be considered as failed (in milliseconds).\n private lockTimeout: number;\n\n // The time that a key will be locked.\n private lockDuration: number;\n\n // A dictionary of key and its lock.\n locks: Record<string, () => Promise<void> | undefined> = {};\n\n // The time that a key-value pair will exist in redis.\n // To this base time will be added between 1 to 2 milliseconds.\n private baseTTL: number;\n\n // The number of retries that we will try to lock a key in case of failure.\n private lockRetries: number;\n\n keyPrefix = KEY_PREFIX;\n\n useLock: boolean;\n\n constructor(options: RedisCacheOptions) {\n this.client = redis.createClient({\n host: options.host || HOST,\n port: options.port || PORT,\n });\n this.locker = promisify(redisLock(this.client, options.lockRetries ?? 10));\n this.lockTimeout = options.lockTimeout ?? DEFAULT_LOCK_TIMEOUT;\n this.lockDuration = options.lockDuration ?? DEFAULT_LOCK_DURATION;\n this.baseTTL = options.ttl ?? DEFAULT_BASE_TTL;\n this.useLock = !!options.useLock;\n }\n\n async get<T = any>(key: string): Promise<T> {\n const keyWithPrefix = KEY_PREFIX + key;\n\n let value;\n try {\n // Try to get the value from redis.\n value = await this.client.getAsync(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to get a value', err);\n }\n\n if (this.useLock) {\n let lock;\n try {\n // Try to lock the key.\n lock = await this.lock(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisLockError('Failed to lock key', err, keyWithPrefix);\n }\n\n // If the lock did not fail, add it to a locks dictionary.\n this.locks[keyWithPrefix] = lock;\n }\n\n return JSON.parse(value);\n }\n\n async getMultiple<T = any>(keys: string[]): Promise<T[]> {\n const keysWithPrefix = keys.map(key => KEY_PREFIX + key);\n let values;\n try {\n if (keysWithPrefix.length === 0) {\n return [];\n }\n // Try to get the value from redis.\n values = await this.client.mgetAsync(keysWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to get a value', err);\n }\n return values.map(value => JSON.parse(value));\n }\n\n async set<T = any>(key: string, value: T): Promise<void> {\n const keyWithPrefix = KEY_PREFIX + key;\n const ttl = parseInt(String(this.baseTTL * (Math.random() + 1)), 10);\n try {\n await this.client.setAsync(keyWithPrefix, JSON.stringify(value), 'EX', ttl);\n if (this.locks[keyWithPrefix]) {\n await this.locks[keyWithPrefix]();\n delete this.locks[keyWithPrefix];\n }\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to set a key-value pair', err);\n }\n }\n\n async setMultiple<T = any>(keyValues: Record<string, T>): Promise<void> {\n if (typeof keyValues !== 'object') {\n const error = new RedisCacheError('keyValues must be an object', new Error('keyValues must be an object'));\n logger.error('keyValues must be an object', { error });\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw error;\n }\n\n if (keyValues === null || keyValues === undefined || Object.keys(keyValues).length === 0) {\n return undefined;\n }\n\n const keyValuesWithPrefix = Object.entries(keyValues).map(([key, value]) => [KEY_PREFIX + key, JSON.stringify(value)]);\n const ttl = Math.trunc(this.baseTTL * (Math.random() + 1));\n try {\n const multi = this.client.multi();\n const setPromise = multi.msetAsync(...keyValuesWithPrefix.flat());\n keyValuesWithPrefix.map(([key]) => multi.expireAsync(key, ttl));\n await multi.exec();\n return setPromise;\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError('Failed to set multiple key-value pairs', err);\n }\n }\n\n async remove(key: string): Promise<void> {\n const keyWithPrefix = KEY_PREFIX + key;\n try {\n if (this.locks[keyWithPrefix]) {\n await this.locks[keyWithPrefix]();\n delete this.locks[keyWithPrefix];\n }\n\n await this.client.delAsync(keyWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError(`Failed to delete key ${keyWithPrefix}`, err);\n }\n }\n\n async removeMultiple(keys: string[]): Promise<void> {\n const keysWithPrefix = keys.map(key => KEY_PREFIX + key);\n try {\n await this.client.delAsync(keysWithPrefix);\n } catch (err) {\n // eslint-disable-next-line @typescript-eslint/only-throw-error\n throw new RedisCacheError(`Failed to delete multiple keys ${keysWithPrefix.join('|')}`, err);\n }\n }\n\n getClient(): any {\n return this.client;\n }\n\n private lock(key: string): Promise<() => Promise<void>> {\n return Promise.race([\n this.locker(key, this.lockDuration),\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n new Promise<never>((_resolve, reject) => setTimeout(() => reject(), this.lockTimeout)),\n ]);\n }\n}\n\nexport default RedisCache;\n","import type { Attributes, Model, ModelStatic, NonNullFindOptions, Sequelize } from 'sequelize';\nimport type { Adapter, AssociationOptions, ModelOptions } from './adapter';\nimport type RedisCache from '../redis';\nimport logger from '../logger';\nimport { promisify } from 'util';\n\nconst { AF_SERVICE_NAME } = process.env;\nconst ORM_CACHE_PREFIX = 'ormCache';\nconst INVALIDATION_HOOKS = ['afterSave', 'afterUpdate', 'afterDestroy'] as const;\nconst BULK_HOOKS = ['beforeBulkUpdate', 'beforeBulkDestroy'] as const;\n\nconst generateInstanceKey = (name: string, id: string): string =>\n `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${name}_${id}`;\n\nconst generateDependencyKey = (modelName: string, associationName: string, associationId: string): string =>\n `${AF_SERVICE_NAME}:${ORM_CACHE_PREFIX}:${modelName}_${associationName}_${associationId}_DEPENDENCIES`;\n\nconst getInstanceDependencyKeys = (modelOptions: ModelOptions, instance): string[] => {\n const keys = modelOptions.associations!\n .filter((associationOptions: AssociationOptions) => instance[associationOptions.alias])\n .map((associationOptions: AssociationOptions): string[] => {\n const accessKey = associationOptions.accessKey!;\n const depKeys: string[] = [];\n if (Array.isArray(instance[associationOptions.alias])) {\n instance[associationOptions.alias].forEach((associationInstance) => {\n depKeys.push(generateDependencyKey(\n modelOptions.name,\n associationOptions.name,\n associationInstance[accessKey],\n ));\n if (associationOptions.innerAssociation && associationInstance[associationOptions.innerAssociation.alias]) {\n depKeys.push(generateDependencyKey(\n modelOptions.name,\n associationOptions.innerAssociation.name,\n associationInstance[associationOptions.innerAssociation.alias][associationOptions.innerAssociation.accessKey!],\n ));\n }\n });\n return depKeys;\n }\n return [\n generateDependencyKey(\n modelOptions.name,\n associationOptions.name,\n instance[associationOptions.alias][accessKey],\n ),\n ];\n });\n return keys.reduce((flattenArray, array) => flattenArray.concat(array), []);\n};\n\nconst handleTransactionHook = (instance, options, func) => {\n const { transaction } = options;\n if (transaction) {\n transaction.afterCommit(() => func(instance));\n } else {\n func(instance);\n }\n};\n\ndeclare module 'sequelize' {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Model {\n function findByPkCached<M extends Model>(\n this: ModelStatic<M>,\n identifier: string,\n scopes: string[],\n options: Omit<NonNullFindOptions<Attributes<M>>, 'where'>\n ): Promise<M>;\n }\n}\n\nexport default class SequelizeAdapter implements Adapter {\n constructor(public ormInstance: Sequelize, public debugMode: boolean) {\n }\n\n getModel(modelName: string): ModelStatic<Model> {\n return this.ormInstance.models[modelName];\n }\n\n getModelDependencies(modelName: string): AssociationOptions[] {\n const { associations } = this.ormInstance.models[modelName];\n return [\n ...Object.keys(associations).map((association) => {\n const sequelizeAssociation = associations[association];\n const associationOptions: AssociationOptions = {\n alias: sequelizeAssociation.as,\n name: sequelizeAssociation.target.name,\n accessKey: sequelizeAssociation.target.primaryKeyAttribute,\n };\n\n // @ts-expect-error through is not defined in the typings\n const { through } = sequelizeAssociation;\n if (through) {\n const relationModel = through.model;\n associationOptions.innerAssociation = {\n alias: relationModel.name,\n name: relationModel.name,\n accessKey: relationModel.primaryKeyAttribute,\n };\n }\n\n return associationOptions;\n }),\n ];\n }\n\n debug(message: string, payload?: unknown): void {\n if (this.debugMode) {\n logger.info(`[ORM_CACHE Debug] ${message}`, payload);\n }\n }\n\n injectGetWithCacheFunction(cache: RedisCache, modelOptions: ModelOptions): void {\n const addDependencies = async (instance) => {\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n const instanceKey = generateInstanceKey(modelOptions.name, instance.id);\n this.debug('Adding dependencies', { instanceKey, dependencyKeys });\n const addDependenciesMulti = cache.getClient().multi();\n const addDependenciesMultiAsync = promisify(addDependenciesMulti.exec).bind(addDependenciesMulti);\n dependencyKeys.reduce((multi, key) => multi.sadd(key, instanceKey), addDependenciesMulti);\n return addDependenciesMultiAsync();\n };\n\n const model = this.getModel(modelOptions.name);\n model.findByPkCached = async <M extends Model>(id: string, scopes: string[], options: Omit<NonNullFindOptions<Attributes<M>>, 'where'>): Promise<M> => {\n const cacheKey = generateInstanceKey(modelOptions.name, id);\n let value = JSON.parse(await cache.getClient().getAsync(cacheKey));\n if (!value) {\n this.debug('Value not found in cache, looking in db', { id, cacheKey });\n value = await model.scope(scopes).findByPk(id, options);\n this.debug('Value from DB', { value: value || 'not found', cacheKey });\n await Promise.all([\n cache.getClient().setAsync(cacheKey, JSON.stringify(value)),\n value && addDependencies(value),\n ]);\n } else {\n value = this.getModel(modelOptions.name).build(value, { isNewRecord: false, include: options.include });\n this.debug('Found cached value', { value, id, cacheKey });\n }\n return value;\n };\n }\n\n addInvalidationHooks(cache: RedisCache, modelOptions: ModelOptions): void {\n const invalidateModelInstance = async (instance) => {\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n const instanceKey = generateInstanceKey(modelOptions.name, instance.id);\n this.debug('Removing dependencies', { instance, instanceKey, dependencyKeys });\n const removeMulti = cache.getClient().multi();\n const removeMultiAsync = promisify(removeMulti.exec).bind(removeMulti);\n dependencyKeys.map(key => removeMulti.srem(key, instanceKey));\n removeMulti.del(instanceKey);\n return removeMultiAsync();\n };\n\n const invalidateModelInstanceByAssociation = async (association, associationId) => {\n const dependentInstancesKeys = await cache.getClient().smembersAsync(generateDependencyKey(\n modelOptions.name,\n association,\n associationId,\n ));\n this.debug('Invalidating dependent instances', { dependentInstancesKeys });\n const removeMulti = cache.getClient().multi();\n const removeMultiAsync = promisify(removeMulti.exec).bind(removeMulti);\n const dependenciesToRemove = await Promise.all(dependentInstancesKeys.map(async (instanceKey) => {\n const instance = JSON.parse(await cache.getClient().getAsync(instanceKey));\n if (!instance) {\n return [];\n }\n const dependencyKeys = getInstanceDependencyKeys(modelOptions, instance);\n dependencyKeys.reduce((multi, key) => multi.srem(key, instanceKey), removeMulti);\n removeMulti.del(instanceKey);\n return dependencyKeys;\n }));\n this.debug('Removing dependencies', { dependentInstancesKeys, dependenciesToRemove });\n return removeMultiAsync();\n };\n\n const model = this.getModel(modelOptions.name);\n INVALIDATION_HOOKS.map(hook => model.addHook(hook, (instance, options) =>\n handleTransactionHook(instance, options, instance => invalidateModelInstance(instance))));\n BULK_HOOKS.map(hook => model.addHook(hook, (options) => {\n options.individualHook = true;\n }));\n\n modelOptions.associations = this.getModelDependencies(modelOptions.name);\n this.debug(`Adding Invalidations Hooks to ${modelOptions.name}'s associations`, { associations: modelOptions.associations });\n modelOptions.associations.forEach((associationOptions) => {\n const associationModel = this.getModel(associationOptions.name);\n INVALIDATION_HOOKS.forEach(hook => associationModel.addHook(hook, (instance, options) =>\n handleTransactionHook(\n instance,\n options,\n associationInstance => invalidateModelInstanceByAssociation(\n associationOptions.name,\n associationInstance[associationOptions.accessKey!],\n ),\n ),\n ));\n BULK_HOOKS.forEach(hook => associationModel.addHook(hook, (options) => {\n options.individualHook = true;\n }));\n\n if (associationOptions.innerAssociation) {\n const innerAssociationModel = this.getModel(associationOptions.innerAssociation.name);\n INVALIDATION_HOOKS.forEach(hook => innerAssociationModel.addHook(hook, (instance, options) =>\n handleTransactionHook(\n instance,\n options,\n innerAssociationInstance => invalidateModelInstanceByAssociation(\n associationOptions.innerAssociation!.name,\n innerAssociationInstance[associationOptions.innerAssociation!.accessKey!],\n ),\n ),\n ));\n BULK_HOOKS.map(hook => innerAssociationModel.addHook(hook, (options) => {\n options.individualHook = true;\n }));\n }\n });\n }\n}\n","export class UnsupportedOrmTypeError extends Error {}\n","import type { Adapter, ModelOptions } from './adapter';\nimport SequelizeAdapter from './sequelize-adapter';\nimport { UnsupportedOrmTypeError } from './errors';\nimport RedisCache from '../redis';\nimport logger from '../logger';\n\nexport enum ORMTypes {\n SEQUELIZE = 'sequelize',\n}\n\ninterface ORMCacheOptions {\n type: ORMTypes;\n models: ModelOptions[];\n ormInstance: any;\n debug: boolean;\n}\n\nconst ORMInstanceFactory = (options: ORMCacheOptions): Adapter => {\n switch (options.type) {\n case ORMTypes.SEQUELIZE: {\n return new SequelizeAdapter(options.ormInstance, options.debug);\n }\n default: {\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n throw new UnsupportedOrmTypeError(`ORM type ${options.type} is unsupported at the moment`);\n }\n }\n};\n\nexport const ORMCache = (options: ORMCacheOptions): void => {\n const { models } = options;\n logger.info('Starting ORM Cache', { options });\n const adapter = ORMInstanceFactory(options);\n const cache = new RedisCache({\n host: process.env.REDIS_HOST,\n port: Number.parseInt(process.env.REDIS_PORT!, 10),\n });\n // eslint-disable-next-line array-callback-return\n models.map((modelOptions): void => {\n adapter.addInvalidationHooks(cache, modelOptions);\n adapter.injectGetWithCacheFunction(cache, modelOptions);\n });\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/matmon",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.10",
|
|
4
4
|
"description": "manage cache",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"node": ">=18"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
|
-
"build": "
|
|
25
|
+
"build": "tsdown",
|
|
26
26
|
"prepublish": "npm run build",
|
|
27
27
|
"coverage": "vitest --coverage",
|
|
28
28
|
"test": "vitest run",
|