@gorgonjs/gorgon 1.4.1 → 1.5.0
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/.eslintrc +5 -85
- package/README.md +2 -2
- package/__tests__/basic.test.ts +91 -74
- package/__tests__/clearmany.test.ts +58 -33
- package/__tests__/concurrency.test.ts +10 -16
- package/__tests__/datePolicy.test.ts +8 -8
- package/__tests__/debug.test.ts +31 -24
- package/__tests__/hooks.test.ts +181 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +433 -0
- package/coverage/coverage-final.json +3 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +131 -0
- package/coverage/library/index.html +116 -0
- package/coverage/library/index.ts.html +1036 -0
- package/coverage/library/provider/index.html +116 -0
- package/coverage/library/provider/memory.ts.html +379 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.es.js +103 -84
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/index.ts +114 -52
- package/package.json +2 -1
package/dist/index.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../provider/memory.ts","../index.ts"],"sourcesContent":["import {IGorgonCacheProvider, GorgonPolicySanitized} from '../index';\n\ninterface IGorgonMemoryCacheProvider extends IGorgonCacheProvider {\n _clear: (key:string) => boolean;\n}\n\n// Created as a function to allow for multiple instances of the memory cache, if needed\nconst MemoryCacheCreator = ():IGorgonMemoryCacheProvider =>{\n\n const cache = {};\n const hOP = cache.hasOwnProperty;\n\n// Memory cache is about the simplist cache possible, use it as an example\n const memoryCache = {\n\n init: async() => {\n // This should be used to update the cache on boot,\n // memory cache will be blank on boot by default\n return;\n },\n\n get: async(key:string) => {\n\n if (hOP.call(cache, key) && cache[key].val) {\n // The cached item exists, return it\n return cache[key].val;\n } else {\n // The cached item does not exist reject\n return undefined;\n }\n\n },\n\n set: async(key:string, value:any, policy: GorgonPolicySanitized) => {\n\n // Clear in case it exists\n await memoryCache.clear(key);\n\n // Set a timemout to self-remove from the cache if in policy\n var to = false as boolean | number;\n\n if (policy && policy.expiry && policy.expiry > 0) {\n to = setTimeout(function() {\n memoryCache.clear(key);\n }, policy.expiry);\n }\n\n // Store the cached item\n cache[key] = {\n policy: policy,\n val: value,\n to: to,\n };\n\n return value;\n\n },\n\n keys: async() => {\n return Object.keys(cache);\n },\n\n clear: async(key?:string) => {\n\n // Clears a single key or complete clear on empty\n // Clear all items in the cache\n if (!key) {\n for (var i in cache) {\n memoryCache._clear(i);\n }\n return true;\n }\n\n return memoryCache._clear(key);\n },\n\n _clear: (key:string) => {\n // Clear a single item, making sure to remove the extra timeout\n if (hOP.call(cache, key)) {\n if (cache[key].to) {\n clearTimeout(cache[key].to);\n }\n\n cache[key] = null;\n delete cache[key];\n return true;\n }\n\n return false;\n },\n\n };\n\n return memoryCache;\n\n}\n\nexport default MemoryCacheCreator;\n","import MemoryCache from './provider/memory';\n\nexport type asyncFunction = () => Promise<any> | (() => any);\nexport type GorgonSettings = {\n debug: boolean;\n defaultProvider: string;\n retry: number;\n}\nexport type GorgonSettingsInput = {\n debug?: boolean;\n defaultProvider?: string;\n retry?: number;\n}\nexport type GorgonPolicy = {\n expiry: number | Date | false;\n provider: string;\n};\nexport type GorgonPolicyInput = GorgonPolicy | number | Date;\nexport type GorgonPolicySanitized = {\n expiry: number | false;\n provider: string;\n};\ntype GorgonCurrentTaskItem = Array<{\n res?: any;\n rej?: any;\n queued: Date;\n}>;\nexport interface IGorgonCacheProvider {\n init: () => Promise<void>;\n get: (key: string) => Promise<any>;\n set: <R>(key: string, value: R, policy: GorgonPolicySanitized) => Promise<R>;\n clear: (key?: string) => Promise<boolean>;\n keys: () => Promise<string[]>;\n}\n\nconst Gorgon = (() => {\n\n const currentTasks = {} as {[key: string]: GorgonCurrentTaskItem};\n const hOP = currentTasks.hasOwnProperty;\n\n const settings = {\n debug: false,\n defaultProvider: 'memory',\n retry: 5000,\n } as GorgonSettings;\n\n const policyMaker = function(incPolicy?: GorgonPolicyInput) {\n const outPolicy = {\n expiry: false,\n provider: settings.defaultProvider,\n } as GorgonPolicySanitized;\n\n // Blank policy, false, or no policy. lets store forever\n if (!incPolicy) {\n return outPolicy;\n }\n\n // Type is a full policy object\n if(incPolicy instanceof Date) {\n var d = new Date();\n\n outPolicy.expiry = Math.ceil((incPolicy.getTime() - d.getTime()) / 1000);\n }else if (typeof incPolicy === 'object' && incPolicy.expiry) {\n if(incPolicy.expiry instanceof Date) {\n outPolicy.expiry = Math.ceil((incPolicy.expiry.getTime() - d.getTime()) / 1000);\n }else{\n outPolicy.expiry = incPolicy.expiry;\n }\n outPolicy.provider = incPolicy.provider || outPolicy.provider;\n } else if(typeof incPolicy === 'object') {\n outPolicy.provider = incPolicy.provider || outPolicy.provider;\n } else if(typeof incPolicy === 'number') {\n outPolicy.expiry = incPolicy;\n }\n\n // Number is too small, negative or not a number\n outPolicy.expiry = outPolicy.expiry && outPolicy.expiry > 0 ? outPolicy.expiry : false;\n\n return outPolicy;\n };\n\n const gorgonCore = {\n\n // Providers available for use\n providers: {} as {[key: string]: IGorgonCacheProvider},\n\n // Allows for settings on the gorgon cache\n settings: (newSettings?: GorgonSettingsInput) => {\n if (!newSettings) {\n return settings;\n }\n\n Object.assign(settings, newSettings); // only overwrite ones sent in; keep others at existing\n\n return settings;\n },\n\n // Add a provider\n addProvider: (name: string, provider:IGorgonCacheProvider) => {\n provider.init(); // Trigger for provider to clear any old cache items or any other cleanup\n gorgonCore.providers[name] = provider;\n },\n\n // Place an item into the cache\n put: async<R>(key:string, value:R, policy?: GorgonPolicyInput):Promise<R> => {\n policy = policyMaker(policy);\n var prov = gorgonCore.providers[policy.provider];\n\n return prov.set(key, value, policyMaker(policy));\n },\n\n // Clear one or all items in the cache\n clear: async(key: string, provider?: string) => {\n\n var prov = gorgonCore.providers[provider || settings.defaultProvider];\n\n // Clear a wildcard search of objects\n if (key && key.indexOf('*') > -1) {\n return prov.keys().then(function(keys) {\n var cacheMatchKeys = keys.filter(function(str) {\n return new RegExp('^' + key.split('*').join('.*') + '$').test(str);\n });\n\n var clearPromises = cacheMatchKeys.map(prov.clear);\n // Incase someone somehow used a wildcard in their cached key (don't do this)\n\n clearPromises.push(prov.clear(key));\n return Promise.all(clearPromises);\n });\n }\n\n // Not a special clear\n return prov.clear(key);\n\n },\n\n // Clear all keys/values in the cache\n clearAll: async(provider?: string) => {\n var prov = gorgonCore.providers[provider || settings.defaultProvider];\n\n return prov.clear();\n },\n\n // Allows you to instantly overwite a cache object\n overwrite: async(key:string, asyncFunc: asyncFunction, policy?: GorgonPolicyInput) => {\n\n try{\n const resolvedData = await asyncFunc();\n\n const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));\n\n return val;\n }catch (e) {\n throw e;\n }\n\n },\n\n // Allows you to get from the cache or pull from the promise\n get: async<R>(key:string, asyncFunc:() => R, policy?: GorgonPolicyInput):Promise<R> => {\n\n policy = policyMaker(policy);\n const prov = gorgonCore.providers[policy.provider];\n\n const currentVal = await prov.get(key); // Most providers will only lookup by key and return false on not found\n\n // If we have a current value sent it out; cache hit!\n if(currentVal !== undefined) {\n if(settings.debug) {console.info('[Gorgon] Cache hit for key: ' + key, currentVal);}\n return currentVal;\n }\n\n // Are we currently already running this cache item?\n if (hOP.call(currentTasks, key) && Array.isArray(currentTasks[key]) && currentTasks[key].length > 0) {\n // Add to the current task, but ignore if any items is below retry anyway threshold\n var oldQueue = false;\n\n for (var i in currentTasks[key]) {\n if(currentTasks[key][i].queued < new Date(Date.now() - settings.retry)) {\n oldQueue = true;\n }\n }\n\n // Add to the current queue\n if(!oldQueue) {\n if(settings.debug) {console.info('[Gorgon] Cache miss, in progress, adding to current queue for key: ' + key);}\n\n var concurent = new Promise(function(resolve: (value: R) => void, reject) {\n currentTasks[key].push({\n res: resolve,\n rej: reject,\n queued: new Date(),\n });\n });\n\n return concurent;\n }\n }else{\n // Add current task to list, this is the first one so the primary\n currentTasks[key] = [{queued: new Date()}];\n }\n\n try{\n if(settings.debug) {console.info('[Gorgon] Cache miss, resolving item for: ' + key);}\n\n // This is the primary item, lets resolve and push it out\n const resolvedData = await asyncFunc();\n\n if(settings.debug) {console.info('[Gorgon] Cache resolved, resolved item for: ' + key, resolvedData);}\n\n const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));\n\n if (hOP.call(currentTasks, key)) {\n for (var i in currentTasks[key]) {\n if(currentTasks[key][i].res) {\n if(settings.debug) {console.info('[Gorgon] Cache queue resolved for: ' + key, resolvedData);}\n\n currentTasks[key][i].res(val);\n }\n }\n\n currentTasks[key] = [];\n delete currentTasks[key];\n }\n\n return val;\n\n }catch (e) {\n if (hOP.call(currentTasks, key)) {\n for (var i in currentTasks[key]) {\n if(currentTasks[key][i].rej) {\n currentTasks[key][i].rej(e);\n }\n }\n\n currentTasks[key] = [];\n delete currentTasks[key];\n }\n\n throw e;\n }\n\n },\n\n\n };\n\n gorgonCore.addProvider('memory', MemoryCache()); // Default provider, light weight and simple\n\n return gorgonCore;\n\n})();\n\nexport {MemoryCache};\nexport default Gorgon;\n"],"names":["MemoryCacheCreator","cache","hOP","memoryCache","key","value","policy","to","Gorgon","currentTasks","settings","policyMaker","incPolicy","outPolicy","d","gorgonCore","newSettings","name","provider","prov","keys","cacheMatchKeys","str","clearPromises","asyncFunc","resolvedData","e","currentVal","oldQueue","i","concurent","resolve","reject","val","MemoryCache"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../provider/memory.ts","../index.ts"],"sourcesContent":["import {IGorgonCacheProvider, GorgonPolicySanitized} from '../index';\n\ninterface IGorgonMemoryCacheProvider extends IGorgonCacheProvider {\n _clear: (key:string) => boolean;\n}\n\n// Created as a function to allow for multiple instances of the memory cache, if needed\nconst MemoryCacheCreator = ():IGorgonMemoryCacheProvider =>{\n\n const cache = {};\n const hOP = cache.hasOwnProperty;\n\n// Memory cache is about the simplist cache possible, use it as an example\n const memoryCache = {\n\n init: async() => {\n // This should be used to update the cache on boot,\n // memory cache will be blank on boot by default\n return;\n },\n\n get: async(key:string) => {\n\n if (hOP.call(cache, key) && cache[key].val) {\n // The cached item exists, return it\n return cache[key].val;\n } else {\n // The cached item does not exist reject\n return undefined;\n }\n\n },\n\n set: async(key:string, value:any, policy: GorgonPolicySanitized) => {\n\n // Clear in case it exists\n await memoryCache.clear(key);\n\n // Set a timemout to self-remove from the cache if in policy\n var to = false as boolean | number;\n\n if (policy && policy.expiry && policy.expiry > 0) {\n to = setTimeout(function() {\n memoryCache.clear(key);\n }, policy.expiry);\n }\n\n // Store the cached item\n cache[key] = {\n policy: policy,\n val: value,\n to: to,\n };\n\n return value;\n\n },\n\n keys: async() => {\n return Object.keys(cache);\n },\n\n clear: async(key?:string) => {\n\n // Clears a single key or complete clear on empty\n // Clear all items in the cache\n if (!key) {\n for (var i in cache) {\n memoryCache._clear(i);\n }\n return true;\n }\n\n return memoryCache._clear(key);\n },\n\n _clear: (key:string) => {\n // Clear a single item, making sure to remove the extra timeout\n if (hOP.call(cache, key)) {\n if (cache[key].to) {\n clearTimeout(cache[key].to);\n }\n\n cache[key] = null;\n delete cache[key];\n return true;\n }\n\n return false;\n },\n\n };\n\n return memoryCache;\n\n}\n\nexport default MemoryCacheCreator;\n","import MemoryCache from './provider/memory';\n\nexport type asyncFunction = () => Promise<any> | (() => any);\nexport type GorgonHookKey =\n | 'settings'\n | 'addProvider'\n | 'put'\n | 'clear'\n | 'clearAll'\n | 'overwrite'\n | 'get'\n | 'valueError';\nexport type GorgonHook = (key: GorgonHookKey, input?: any, output?: any) => void;\nexport type GorgonSettings = {\n debug: boolean;\n defaultProvider: string;\n retry: number;\n};\nexport type GorgonSettingsInput = {\n debug?: boolean;\n defaultProvider?: string;\n retry?: number;\n};\nexport type GorgonPolicy = {\n expiry: number | Date | false;\n provider: string;\n};\nexport type GorgonPolicyInput = GorgonPolicy | number | Date;\nexport type GorgonPolicySanitized = {\n expiry: number | false;\n provider: string;\n};\ntype GorgonCurrentTaskItem = Array<{\n res?: any;\n rej?: any;\n queued: Date;\n}>;\nexport interface IGorgonCacheProvider {\n init: () => Promise<void>;\n get: (key: string) => Promise<any>;\n set: <R>(key: string, value: R, policy: GorgonPolicySanitized) => Promise<R>;\n clear: (key?: string) => Promise<boolean>;\n keys: () => Promise<string[]>;\n}\n\nconst Gorgon = (() => {\n const currentTasks = {} as { [key: string]: GorgonCurrentTaskItem };\n const hOP = currentTasks.hasOwnProperty;\n\n const settings = {\n debug: false,\n defaultProvider: 'memory',\n retry: 5000,\n } as GorgonSettings;\n\n const policyMaker = function (incPolicy?: GorgonPolicyInput) {\n const outPolicy = {\n expiry: false,\n provider: settings.defaultProvider,\n } as GorgonPolicySanitized;\n\n // Blank policy, false, or no policy. lets store forever\n if (!incPolicy) {\n return outPolicy;\n }\n\n // Type is a full policy object\n if (incPolicy instanceof Date) {\n var d = new Date();\n\n outPolicy.expiry = Math.ceil((incPolicy.getTime() - d.getTime()) / 1000);\n } else if (typeof incPolicy === 'object' && incPolicy.expiry) {\n if (incPolicy.expiry instanceof Date) {\n outPolicy.expiry = Math.ceil((incPolicy.expiry.getTime() - d.getTime()) / 1000);\n } else {\n outPolicy.expiry = incPolicy.expiry;\n }\n outPolicy.provider = incPolicy.provider || outPolicy.provider;\n } else if (typeof incPolicy === 'object') {\n outPolicy.provider = incPolicy.provider || outPolicy.provider;\n } else if (typeof incPolicy === 'number') {\n outPolicy.expiry = incPolicy;\n }\n\n // Number is too small, negative or not a number\n outPolicy.expiry = outPolicy.expiry && outPolicy.expiry > 0 ? outPolicy.expiry : false;\n\n return outPolicy;\n };\n\n const gorgonCore = {\n // Providers available for use\n providers: {} as { [key: string]: IGorgonCacheProvider },\n\n // Hooks\n hooks: {} as { [key: string]: Array<GorgonHook> },\n\n _callHooks: (key: GorgonHookKey, input?: any, output?: any) => {\n if (hOP.call(gorgonCore.hooks, key)) {\n for (var i in gorgonCore.hooks[key]) {\n if (typeof gorgonCore.hooks[key][i] === 'function') {\n try {\n gorgonCore.hooks[key][i](key, input, output);\n } catch (e) {\n console.error('[Gorgon] Hook error for hook: ' + key, e);\n }\n }\n }\n }\n },\n\n // Allows for settings on the gorgon cache\n settings: (newSettings?: GorgonSettingsInput) => {\n if (!newSettings) {\n return settings;\n }\n\n Object.assign(settings, newSettings); // only overwrite ones sent in; keep others at existing\n\n gorgonCore._callHooks('settings', newSettings, settings);\n\n return settings;\n },\n\n // add a hook or array of hooks\n addHook: (key: GorgonHookKey, hook: GorgonHook | Array<GorgonHook>) => {\n if (!hOP.call(gorgonCore.hooks, key)) {\n gorgonCore.hooks[key] = [];\n }\n\n if (Array.isArray(hook)) {\n gorgonCore.hooks[key] = gorgonCore.hooks[key].concat(hook);\n } else {\n gorgonCore.hooks[key].push(hook);\n }\n },\n\n // Add a provider\n addProvider: (name: string, provider: IGorgonCacheProvider) => {\n provider.init(); // Trigger for provider to clear any old cache items or any other cleanup\n gorgonCore.providers[name] = provider;\n\n gorgonCore._callHooks('addProvider', { name, provider });\n },\n\n // Place an item into the cache\n put: async <R>(key: string, value: R, policy?: GorgonPolicyInput): Promise<R> => {\n policy = policyMaker(policy);\n var prov = gorgonCore.providers[policy.provider];\n\n gorgonCore._callHooks('put', { key, value, policy }, value);\n\n return prov.set(key, value, policyMaker(policy));\n },\n\n // Clear one or all items in the cache\n clear: async (key: string, provider?: string) => {\n var prov = gorgonCore.providers[provider || settings.defaultProvider];\n\n gorgonCore._callHooks('clear', { key, provider });\n\n // Clear a wildcard search of objects\n if (key && key.indexOf('*') > -1) {\n return prov.keys().then(function (keys) {\n var cacheMatchKeys = keys.filter(function (str) {\n return new RegExp('^' + key.split('*').join('.*') + '$').test(str);\n });\n\n var clearPromises = cacheMatchKeys.map(prov.clear);\n // Incase someone somehow used a wildcard in their cached key (don't do this)\n\n clearPromises.push(prov.clear(key));\n return Promise.all(clearPromises);\n });\n }\n\n // Not a special clear\n return prov.clear(key);\n },\n\n // Clear all keys/values in the cache\n clearAll: async (provider?: string) => {\n var prov = gorgonCore.providers[provider || settings.defaultProvider];\n\n gorgonCore._callHooks('clearAll', { provider });\n\n return prov.clear();\n },\n\n // Allows you to instantly overwite a cache object\n overwrite: async (key: string, asyncFunc: asyncFunction, policy?: GorgonPolicyInput) => {\n try {\n const resolvedData = await asyncFunc();\n\n const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));\n\n gorgonCore._callHooks('overwrite', { key, asyncFunc, policy }, val);\n\n return val;\n } catch (e) {\n throw e;\n }\n },\n\n // Allows you to get from the cache or pull from the promise\n get: async <R>(key: string, asyncFunc: () => R, policy?: GorgonPolicyInput): Promise<R> => {\n policy = policyMaker(policy);\n const prov = gorgonCore.providers[policy.provider];\n\n const currentVal = await prov.get(key); // Most providers will only lookup by key and return false on not found\n\n // If we have a current value sent it out; cache hit!\n if (currentVal !== undefined) {\n if (settings.debug) {\n console.info('[Gorgon] Cache hit for key: ' + key, currentVal);\n }\n\n gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: true, queued: false }, currentVal);\n\n return currentVal;\n }\n\n // Are we currently already running this cache item?\n if (hOP.call(currentTasks, key) && Array.isArray(currentTasks[key]) && currentTasks[key].length > 0) {\n // Add to the current task, but ignore if any items is below retry anyway threshold\n var oldQueue = false;\n\n for (var i in currentTasks[key]) {\n if (currentTasks[key][i].queued < new Date(Date.now() - settings.retry)) {\n oldQueue = true;\n }\n }\n\n // Add to the current queue\n if (!oldQueue) {\n if (settings.debug) {\n console.info('[Gorgon] Cache miss, in progress, adding to current queue for key: ' + key);\n }\n\n var concurent = new Promise(function (resolve: (value: R) => void, reject) {\n currentTasks[key].push({\n res: resolve,\n rej: reject,\n queued: new Date(),\n });\n });\n\n gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: false, queued: true }, concurent);\n\n return concurent;\n }\n } else {\n // Add current task to list, this is the first one so the primary\n currentTasks[key] = [{ queued: new Date() }];\n }\n\n try {\n if (settings.debug) {\n console.info('[Gorgon] Cache miss, resolving item for: ' + key);\n }\n\n // This is the primary item\n const resolver = asyncFunc();\n\n gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: false, queued: false }, resolver);\n\n // wait for it to finish then push it out\n const resolvedData = await resolver;\n\n if (settings.debug) {\n console.info('[Gorgon] Cache resolved, resolved item for: ' + key, resolvedData);\n }\n\n const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));\n\n if (hOP.call(currentTasks, key)) {\n for (var i in currentTasks[key]) {\n if (currentTasks[key][i].res) {\n if (settings.debug) {\n console.info('[Gorgon] Cache queue resolved for: ' + key, resolvedData);\n }\n\n currentTasks[key][i].res(val);\n }\n }\n\n currentTasks[key] = [];\n delete currentTasks[key];\n }\n\n return val;\n } catch (e) {\n if (hOP.call(currentTasks, key)) {\n for (var i in currentTasks[key]) {\n if (currentTasks[key][i].rej) {\n currentTasks[key][i].rej(e);\n }\n }\n\n gorgonCore._callHooks('valueError', { key, asyncFunc, policy, cacheHit: false, queued: false }, e);\n\n currentTasks[key] = [];\n delete currentTasks[key];\n }\n\n throw e;\n }\n },\n };\n\n gorgonCore.addProvider('memory', MemoryCache()); // Default provider, light weight and simple\n\n return gorgonCore;\n})();\n\nexport { MemoryCache };\nexport default Gorgon;\n"],"names":["MemoryCacheCreator","cache","hOP","memoryCache","key","value","policy","to","i","Gorgon","currentTasks","settings","policyMaker","incPolicy","outPolicy","d","gorgonCore","input","output","e","newSettings","hook","name","provider","prov","keys","cacheMatchKeys","str","clearPromises","asyncFunc","resolvedData","val","currentVal","oldQueue","concurent","resolve","reject","resolver","MemoryCache"],"mappings":"8NAOM,MAAAA,EAAqB,IAAgC,CAEzD,MAAMC,EAAQ,CAAA,EACRC,EAAMD,EAAM,eAGZE,EAAc,CAElB,KAAM,SAAW,CAIjB,EAEA,IAAK,MAAMC,GAAe,CAEpB,GAAAF,EAAI,KAAKD,EAAOG,CAAG,GAAKH,EAAMG,CAAG,EAAE,IAE9B,OAAAH,EAAMG,CAAG,EAAE,GAMtB,EAEA,IAAK,MAAMA,EAAYC,EAAWC,IAAkC,CAG3D,MAAAH,EAAY,MAAMC,CAAG,EAG5B,IAAIG,EAAK,GAET,OAAID,GAAUA,EAAO,QAAUA,EAAO,OAAS,IAC7CC,EAAK,WAAW,UAAW,CACzBJ,EAAY,MAAMC,CAAG,CAAA,EACpBE,EAAO,MAAM,GAIlBL,EAAMG,CAAG,EAAI,CACX,OAAAE,EACA,IAAKD,EACL,GAAAE,CAAA,EAGKF,CAET,EAEA,KAAM,SACG,OAAO,KAAKJ,CAAK,EAG1B,MAAO,MAAMG,GAAgB,CAI3B,GAAI,CAACA,EAAK,CACR,QAASI,KAAKP,EACZE,EAAY,OAAOK,CAAC,EAEf,MAAA,EACT,CAEO,OAAAL,EAAY,OAAOC,CAAG,CAC/B,EAEA,OAASA,GAEHF,EAAI,KAAKD,EAAOG,CAAG,GACjBH,EAAMG,CAAG,EAAE,IACA,aAAAH,EAAMG,CAAG,EAAE,EAAE,EAG5BH,EAAMG,CAAG,EAAI,KACb,OAAOH,EAAMG,CAAG,EACT,IAGF,EACT,EAIK,OAAAD,CAET,EClDMM,GAAU,IAAM,CACpB,MAAMC,EAAe,CAAA,EACfR,EAAMQ,EAAa,eAEnBC,EAAW,CACf,MAAO,GACP,gBAAiB,SACjB,MAAO,GAAA,EAGHC,EAAc,SAAUC,EAA+B,CAC3D,MAAMC,EAAY,CAChB,OAAQ,GACR,SAAUH,EAAS,eAAA,EAIrB,GAAI,CAACE,EACI,OAAAC,EAIT,GAAID,aAAqB,KAAM,CACzB,IAAAE,MAAQ,KAEFD,EAAA,OAAS,KAAK,MAAMD,EAAU,UAAYE,EAAE,QAAQ,GAAK,GAAI,CAC9D,MAAA,OAAOF,GAAc,UAAYA,EAAU,QAChDA,EAAU,kBAAkB,KACpBC,EAAA,OAAS,KAAK,MAAMD,EAAU,OAAO,QAAY,EAAAE,EAAE,QAAQ,GAAK,GAAI,EAE9ED,EAAU,OAASD,EAAU,OAErBC,EAAA,SAAWD,EAAU,UAAYC,EAAU,UAC5C,OAAOD,GAAc,SACpBC,EAAA,SAAWD,EAAU,UAAYC,EAAU,SAC5C,OAAOD,GAAc,WAC9BC,EAAU,OAASD,GAIrB,OAAAC,EAAU,OAASA,EAAU,QAAUA,EAAU,OAAS,EAAIA,EAAU,OAAS,GAE1EA,CAAA,EAGHE,EAAa,CAEjB,UAAW,CAAC,EAGZ,MAAO,CAAC,EAER,WAAY,CAACZ,EAAoBa,EAAaC,IAAiB,CAC7D,GAAIhB,EAAI,KAAKc,EAAW,MAAOZ,CAAG,GAChC,QAAS,KAAKY,EAAW,MAAMZ,CAAG,EAChC,GAAI,OAAOY,EAAW,MAAMZ,CAAG,EAAE,CAAC,GAAM,WAClC,GAAA,CACFY,EAAW,MAAMZ,CAAG,EAAE,CAAC,EAAEA,EAAKa,EAAOC,CAAM,QACpCC,EAAG,CACF,QAAA,MAAM,iCAAmCf,EAAKe,CAAC,CACzD,EAIR,EAGA,SAAWC,IACJA,IAIE,OAAA,OAAOT,EAAUS,CAAW,EAExBJ,EAAA,WAAW,WAAYI,EAAaT,CAAQ,GAEhDA,GAIT,QAAS,CAACP,EAAoBiB,IAAyC,CAChEnB,EAAI,KAAKc,EAAW,MAAOZ,CAAG,IACtBY,EAAA,MAAMZ,CAAG,EAAI,IAGtB,MAAM,QAAQiB,CAAI,EACTL,EAAA,MAAMZ,CAAG,EAAIY,EAAW,MAAMZ,CAAG,EAAE,OAAOiB,CAAI,EAEzDL,EAAW,MAAMZ,CAAG,EAAE,KAAKiB,CAAI,CAEnC,EAGA,YAAa,CAACC,EAAcC,IAAmC,CAC7DA,EAAS,KAAK,EACHP,EAAA,UAAUM,CAAI,EAAIC,EAE7BP,EAAW,WAAW,cAAe,CAAE,KAAAM,EAAM,SAAAC,CAAU,CAAA,CACzD,EAGA,IAAK,MAAUnB,EAAaC,EAAUC,IAA2C,CAC/EA,EAASM,EAAYN,CAAM,EAC3B,IAAIkB,EAAOR,EAAW,UAAUV,EAAO,QAAQ,EAE/C,OAAAU,EAAW,WAAW,MAAO,CAAE,IAAAZ,EAAK,MAAAC,EAAO,OAAAC,CAAA,EAAUD,CAAK,EAEnDmB,EAAK,IAAIpB,EAAKC,EAAOO,EAAYN,CAAM,CAAC,CACjD,EAGA,MAAO,MAAOF,EAAamB,IAAsB,CAC/C,IAAIC,EAAOR,EAAW,UAAUO,GAAYZ,EAAS,eAAe,EAKpE,OAHAK,EAAW,WAAW,QAAS,CAAE,IAAAZ,EAAK,SAAAmB,CAAU,CAAA,EAG5CnB,GAAOA,EAAI,QAAQ,GAAG,EAAI,GACrBoB,EAAK,KAAA,EAAO,KAAK,SAAUC,EAAM,CACtC,IAAIC,EAAiBD,EAAK,OAAO,SAAUE,EAAK,CAC9C,OAAO,IAAI,OAAO,IAAMvB,EAAI,MAAM,GAAG,EAAE,KAAK,IAAI,EAAI,GAAG,EAAE,KAAKuB,CAAG,CAAA,CAClE,EAEGC,EAAgBF,EAAe,IAAIF,EAAK,KAAK,EAGjD,OAAAI,EAAc,KAAKJ,EAAK,MAAMpB,CAAG,CAAC,EAC3B,QAAQ,IAAIwB,CAAa,CAAA,CACjC,EAIIJ,EAAK,MAAMpB,CAAG,CACvB,EAGA,SAAU,MAAOmB,GAAsB,CACrC,IAAIC,EAAOR,EAAW,UAAUO,GAAYZ,EAAS,eAAe,EAEpE,OAAAK,EAAW,WAAW,WAAY,CAAE,SAAAO,CAAU,CAAA,EAEvCC,EAAK,OACd,EAGA,UAAW,MAAOpB,EAAayB,EAA0BvB,IAA+B,CAClF,GAAA,CACI,MAAAwB,EAAe,MAAMD,IAErBE,EAAM,MAAMf,EAAW,IAAIZ,EAAK0B,EAAclB,EAAYN,CAAM,CAAC,EAEvE,OAAAU,EAAW,WAAW,YAAa,CAAE,IAAAZ,EAAK,UAAAyB,EAAW,OAAAvB,CAAA,EAAUyB,CAAG,EAE3DA,QACAZ,EAAG,CACJ,MAAAA,CACR,CACF,EAGA,IAAK,MAAUf,EAAayB,EAAoBvB,IAA2C,CACzFA,EAASM,EAAYN,CAAM,EAG3B,MAAM0B,EAAa,MAFNhB,EAAW,UAAUV,EAAO,QAAQ,EAEnB,IAAIF,CAAG,EAGrC,GAAI4B,IAAe,OACjB,OAAIrB,EAAS,OACH,QAAA,KAAK,+BAAiCP,EAAK4B,CAAU,EAGpDhB,EAAA,WAAW,MAAO,CAAE,IAAAZ,EAAK,UAAAyB,EAAW,OAAAvB,EAAQ,SAAU,GAAM,OAAQ,EAAM,EAAG0B,CAAU,EAE3FA,EAIT,GAAI9B,EAAI,KAAKQ,EAAcN,CAAG,GAAK,MAAM,QAAQM,EAAaN,CAAG,CAAC,GAAKM,EAAaN,CAAG,EAAE,OAAS,EAAG,CAEnG,IAAI6B,EAAW,GAEN,QAAAzB,KAAKE,EAAaN,CAAG,EACxBM,EAAaN,CAAG,EAAEI,CAAC,EAAE,OAAS,IAAI,KAAK,KAAK,IAAA,EAAQG,EAAS,KAAK,IACzDsB,EAAA,IAKf,GAAI,CAACA,EAAU,CACTtB,EAAS,OACH,QAAA,KAAK,sEAAwEP,CAAG,EAG1F,IAAI8B,EAAY,IAAI,QAAQ,SAAUC,EAA6BC,EAAQ,CAC5D1B,EAAAN,CAAG,EAAE,KAAK,CACrB,IAAK+B,EACL,IAAKC,EACL,WAAY,IAAK,CAClB,CAAA,CACF,EAEU,OAAApB,EAAA,WAAW,MAAO,CAAE,IAAAZ,EAAK,UAAAyB,EAAW,OAAAvB,EAAQ,SAAU,GAAO,OAAQ,EAAK,EAAG4B,CAAS,EAE1FA,CACT,CAAA,MAGaxB,EAAAN,CAAG,EAAI,CAAC,CAAE,OAAY,IAAA,KAAQ,EAGzC,GAAA,CACEO,EAAS,OACH,QAAA,KAAK,4CAA8CP,CAAG,EAIhE,MAAMiC,EAAWR,IAENb,EAAA,WAAW,MAAO,CAAE,IAAAZ,EAAK,UAAAyB,EAAW,OAAAvB,EAAQ,SAAU,GAAO,OAAQ,EAAM,EAAG+B,CAAQ,EAGjG,MAAMP,EAAe,MAAMO,EAEvB1B,EAAS,OACH,QAAA,KAAK,+CAAiDP,EAAK0B,CAAY,EAG3E,MAAAC,EAAM,MAAMf,EAAW,IAAIZ,EAAK0B,EAAclB,EAAYN,CAAM,CAAC,EAEvE,GAAIJ,EAAI,KAAKQ,EAAcN,CAAG,EAAG,CACtB,QAAAI,KAAKE,EAAaN,CAAG,EACxBM,EAAaN,CAAG,EAAEI,CAAC,EAAE,MACnBG,EAAS,OACH,QAAA,KAAK,sCAAwCP,EAAK0B,CAAY,EAGxEpB,EAAaN,CAAG,EAAEI,CAAC,EAAE,IAAIuB,CAAG,GAInBrB,EAAAN,CAAG,EAAI,GACpB,OAAOM,EAAaN,CAAG,CACzB,CAEO,OAAA2B,QACAZ,EAAG,CACV,GAAIjB,EAAI,KAAKQ,EAAcN,CAAG,EAAG,CACtB,QAAAI,KAAKE,EAAaN,CAAG,EACxBM,EAAaN,CAAG,EAAEI,CAAC,EAAE,KACvBE,EAAaN,CAAG,EAAEI,CAAC,EAAE,IAAIW,CAAC,EAInBH,EAAA,WAAW,aAAc,CAAE,IAAAZ,EAAK,UAAAyB,EAAW,OAAAvB,EAAQ,SAAU,GAAO,OAAQ,EAAM,EAAGa,CAAC,EAEpFT,EAAAN,CAAG,EAAI,GACpB,OAAOM,EAAaN,CAAG,CACzB,CAEM,MAAAe,CACR,CACF,CAAA,EAGS,OAAAH,EAAA,YAAY,SAAUsB,EAAa,CAAA,EAEvCtB,CACT,GAAG"}
|
package/index.ts
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
import MemoryCache from './provider/memory';
|
|
2
2
|
|
|
3
3
|
export type asyncFunction = () => Promise<any> | (() => any);
|
|
4
|
+
export type GorgonHookKey =
|
|
5
|
+
| 'settings'
|
|
6
|
+
| 'addProvider'
|
|
7
|
+
| 'put'
|
|
8
|
+
| 'clear'
|
|
9
|
+
| 'clearAll'
|
|
10
|
+
| 'overwrite'
|
|
11
|
+
| 'get'
|
|
12
|
+
| 'valueError';
|
|
13
|
+
export type GorgonHook = (key: GorgonHookKey, input?: any, output?: any) => void;
|
|
4
14
|
export type GorgonSettings = {
|
|
5
15
|
debug: boolean;
|
|
6
16
|
defaultProvider: string;
|
|
7
17
|
retry: number;
|
|
8
|
-
}
|
|
18
|
+
};
|
|
9
19
|
export type GorgonSettingsInput = {
|
|
10
20
|
debug?: boolean;
|
|
11
21
|
defaultProvider?: string;
|
|
12
22
|
retry?: number;
|
|
13
|
-
}
|
|
23
|
+
};
|
|
14
24
|
export type GorgonPolicy = {
|
|
15
25
|
expiry: number | Date | false;
|
|
16
26
|
provider: string;
|
|
@@ -34,8 +44,7 @@ export interface IGorgonCacheProvider {
|
|
|
34
44
|
}
|
|
35
45
|
|
|
36
46
|
const Gorgon = (() => {
|
|
37
|
-
|
|
38
|
-
const currentTasks = {} as {[key: string]: GorgonCurrentTaskItem};
|
|
47
|
+
const currentTasks = {} as { [key: string]: GorgonCurrentTaskItem };
|
|
39
48
|
const hOP = currentTasks.hasOwnProperty;
|
|
40
49
|
|
|
41
50
|
const settings = {
|
|
@@ -44,7 +53,7 @@ const Gorgon = (() => {
|
|
|
44
53
|
retry: 5000,
|
|
45
54
|
} as GorgonSettings;
|
|
46
55
|
|
|
47
|
-
const policyMaker = function(incPolicy?: GorgonPolicyInput) {
|
|
56
|
+
const policyMaker = function (incPolicy?: GorgonPolicyInput) {
|
|
48
57
|
const outPolicy = {
|
|
49
58
|
expiry: false,
|
|
50
59
|
provider: settings.defaultProvider,
|
|
@@ -56,20 +65,20 @@ const Gorgon = (() => {
|
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
// Type is a full policy object
|
|
59
|
-
if(incPolicy instanceof Date) {
|
|
68
|
+
if (incPolicy instanceof Date) {
|
|
60
69
|
var d = new Date();
|
|
61
70
|
|
|
62
71
|
outPolicy.expiry = Math.ceil((incPolicy.getTime() - d.getTime()) / 1000);
|
|
63
|
-
}else if (typeof incPolicy === 'object' && incPolicy.expiry) {
|
|
64
|
-
if(incPolicy.expiry instanceof Date) {
|
|
72
|
+
} else if (typeof incPolicy === 'object' && incPolicy.expiry) {
|
|
73
|
+
if (incPolicy.expiry instanceof Date) {
|
|
65
74
|
outPolicy.expiry = Math.ceil((incPolicy.expiry.getTime() - d.getTime()) / 1000);
|
|
66
|
-
}else{
|
|
75
|
+
} else {
|
|
67
76
|
outPolicy.expiry = incPolicy.expiry;
|
|
68
77
|
}
|
|
69
78
|
outPolicy.provider = incPolicy.provider || outPolicy.provider;
|
|
70
|
-
} else if(typeof incPolicy === 'object') {
|
|
79
|
+
} else if (typeof incPolicy === 'object') {
|
|
71
80
|
outPolicy.provider = incPolicy.provider || outPolicy.provider;
|
|
72
|
-
} else if(typeof incPolicy === 'number') {
|
|
81
|
+
} else if (typeof incPolicy === 'number') {
|
|
73
82
|
outPolicy.expiry = incPolicy;
|
|
74
83
|
}
|
|
75
84
|
|
|
@@ -80,9 +89,25 @@ const Gorgon = (() => {
|
|
|
80
89
|
};
|
|
81
90
|
|
|
82
91
|
const gorgonCore = {
|
|
83
|
-
|
|
84
92
|
// Providers available for use
|
|
85
|
-
providers: {} as {[key: string]: IGorgonCacheProvider},
|
|
93
|
+
providers: {} as { [key: string]: IGorgonCacheProvider },
|
|
94
|
+
|
|
95
|
+
// Hooks
|
|
96
|
+
hooks: {} as { [key: string]: Array<GorgonHook> },
|
|
97
|
+
|
|
98
|
+
_callHooks: (key: GorgonHookKey, input?: any, output?: any) => {
|
|
99
|
+
if (hOP.call(gorgonCore.hooks, key)) {
|
|
100
|
+
for (var i in gorgonCore.hooks[key]) {
|
|
101
|
+
if (typeof gorgonCore.hooks[key][i] === 'function') {
|
|
102
|
+
try {
|
|
103
|
+
gorgonCore.hooks[key][i](key, input, output);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
console.error('[Gorgon] Hook error for hook: ' + key, e);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
86
111
|
|
|
87
112
|
// Allows for settings on the gorgon cache
|
|
88
113
|
settings: (newSettings?: GorgonSettingsInput) => {
|
|
@@ -92,32 +117,52 @@ const Gorgon = (() => {
|
|
|
92
117
|
|
|
93
118
|
Object.assign(settings, newSettings); // only overwrite ones sent in; keep others at existing
|
|
94
119
|
|
|
120
|
+
gorgonCore._callHooks('settings', newSettings, settings);
|
|
121
|
+
|
|
95
122
|
return settings;
|
|
96
123
|
},
|
|
97
124
|
|
|
125
|
+
// add a hook or array of hooks
|
|
126
|
+
addHook: (key: GorgonHookKey, hook: GorgonHook | Array<GorgonHook>) => {
|
|
127
|
+
if (!hOP.call(gorgonCore.hooks, key)) {
|
|
128
|
+
gorgonCore.hooks[key] = [];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (Array.isArray(hook)) {
|
|
132
|
+
gorgonCore.hooks[key] = gorgonCore.hooks[key].concat(hook);
|
|
133
|
+
} else {
|
|
134
|
+
gorgonCore.hooks[key].push(hook);
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
98
138
|
// Add a provider
|
|
99
|
-
addProvider: (name: string, provider:IGorgonCacheProvider) => {
|
|
139
|
+
addProvider: (name: string, provider: IGorgonCacheProvider) => {
|
|
100
140
|
provider.init(); // Trigger for provider to clear any old cache items or any other cleanup
|
|
101
141
|
gorgonCore.providers[name] = provider;
|
|
142
|
+
|
|
143
|
+
gorgonCore._callHooks('addProvider', { name, provider });
|
|
102
144
|
},
|
|
103
145
|
|
|
104
146
|
// Place an item into the cache
|
|
105
|
-
put: async<R>(key:string, value:R, policy?: GorgonPolicyInput):Promise<R> => {
|
|
147
|
+
put: async <R>(key: string, value: R, policy?: GorgonPolicyInput): Promise<R> => {
|
|
106
148
|
policy = policyMaker(policy);
|
|
107
149
|
var prov = gorgonCore.providers[policy.provider];
|
|
108
150
|
|
|
151
|
+
gorgonCore._callHooks('put', { key, value, policy }, value);
|
|
152
|
+
|
|
109
153
|
return prov.set(key, value, policyMaker(policy));
|
|
110
154
|
},
|
|
111
155
|
|
|
112
|
-
|
|
113
|
-
clear: async(key: string, provider?: string) => {
|
|
114
|
-
|
|
156
|
+
// Clear one or all items in the cache
|
|
157
|
+
clear: async (key: string, provider?: string) => {
|
|
115
158
|
var prov = gorgonCore.providers[provider || settings.defaultProvider];
|
|
116
159
|
|
|
160
|
+
gorgonCore._callHooks('clear', { key, provider });
|
|
161
|
+
|
|
117
162
|
// Clear a wildcard search of objects
|
|
118
163
|
if (key && key.indexOf('*') > -1) {
|
|
119
|
-
return prov.keys().then(function(keys) {
|
|
120
|
-
var cacheMatchKeys = keys.filter(function(str) {
|
|
164
|
+
return prov.keys().then(function (keys) {
|
|
165
|
+
var cacheMatchKeys = keys.filter(function (str) {
|
|
121
166
|
return new RegExp('^' + key.split('*').join('.*') + '$').test(str);
|
|
122
167
|
});
|
|
123
168
|
|
|
@@ -131,42 +176,47 @@ const Gorgon = (() => {
|
|
|
131
176
|
|
|
132
177
|
// Not a special clear
|
|
133
178
|
return prov.clear(key);
|
|
134
|
-
|
|
135
179
|
},
|
|
136
180
|
|
|
137
181
|
// Clear all keys/values in the cache
|
|
138
|
-
clearAll: async(provider?: string) => {
|
|
182
|
+
clearAll: async (provider?: string) => {
|
|
139
183
|
var prov = gorgonCore.providers[provider || settings.defaultProvider];
|
|
140
184
|
|
|
185
|
+
gorgonCore._callHooks('clearAll', { provider });
|
|
186
|
+
|
|
141
187
|
return prov.clear();
|
|
142
188
|
},
|
|
143
189
|
|
|
144
190
|
// Allows you to instantly overwite a cache object
|
|
145
|
-
overwrite: async(key:string, asyncFunc: asyncFunction, policy?: GorgonPolicyInput) => {
|
|
146
|
-
|
|
147
|
-
try{
|
|
191
|
+
overwrite: async (key: string, asyncFunc: asyncFunction, policy?: GorgonPolicyInput) => {
|
|
192
|
+
try {
|
|
148
193
|
const resolvedData = await asyncFunc();
|
|
149
194
|
|
|
150
195
|
const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));
|
|
151
196
|
|
|
197
|
+
gorgonCore._callHooks('overwrite', { key, asyncFunc, policy }, val);
|
|
198
|
+
|
|
152
199
|
return val;
|
|
153
|
-
}catch (e) {
|
|
200
|
+
} catch (e) {
|
|
154
201
|
throw e;
|
|
155
202
|
}
|
|
156
|
-
|
|
157
203
|
},
|
|
158
204
|
|
|
159
205
|
// Allows you to get from the cache or pull from the promise
|
|
160
|
-
get: async<R>(key:string, asyncFunc:() => R, policy?: GorgonPolicyInput):Promise<R> => {
|
|
161
|
-
|
|
206
|
+
get: async <R>(key: string, asyncFunc: () => R, policy?: GorgonPolicyInput): Promise<R> => {
|
|
162
207
|
policy = policyMaker(policy);
|
|
163
208
|
const prov = gorgonCore.providers[policy.provider];
|
|
164
209
|
|
|
165
210
|
const currentVal = await prov.get(key); // Most providers will only lookup by key and return false on not found
|
|
166
211
|
|
|
167
212
|
// If we have a current value sent it out; cache hit!
|
|
168
|
-
if(currentVal !== undefined) {
|
|
169
|
-
if(settings.debug) {
|
|
213
|
+
if (currentVal !== undefined) {
|
|
214
|
+
if (settings.debug) {
|
|
215
|
+
console.info('[Gorgon] Cache hit for key: ' + key, currentVal);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: true, queued: false }, currentVal);
|
|
219
|
+
|
|
170
220
|
return currentVal;
|
|
171
221
|
}
|
|
172
222
|
|
|
@@ -176,16 +226,18 @@ const Gorgon = (() => {
|
|
|
176
226
|
var oldQueue = false;
|
|
177
227
|
|
|
178
228
|
for (var i in currentTasks[key]) {
|
|
179
|
-
if(currentTasks[key][i].queued < new Date(Date.now() - settings.retry)) {
|
|
229
|
+
if (currentTasks[key][i].queued < new Date(Date.now() - settings.retry)) {
|
|
180
230
|
oldQueue = true;
|
|
181
231
|
}
|
|
182
232
|
}
|
|
183
233
|
|
|
184
234
|
// Add to the current queue
|
|
185
|
-
if(!oldQueue) {
|
|
186
|
-
if(settings.debug) {
|
|
235
|
+
if (!oldQueue) {
|
|
236
|
+
if (settings.debug) {
|
|
237
|
+
console.info('[Gorgon] Cache miss, in progress, adding to current queue for key: ' + key);
|
|
238
|
+
}
|
|
187
239
|
|
|
188
|
-
var concurent = new Promise(function(resolve: (value: R) => void, reject) {
|
|
240
|
+
var concurent = new Promise(function (resolve: (value: R) => void, reject) {
|
|
189
241
|
currentTasks[key].push({
|
|
190
242
|
res: resolve,
|
|
191
243
|
rej: reject,
|
|
@@ -193,27 +245,40 @@ const Gorgon = (() => {
|
|
|
193
245
|
});
|
|
194
246
|
});
|
|
195
247
|
|
|
248
|
+
gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: false, queued: true }, concurent);
|
|
249
|
+
|
|
196
250
|
return concurent;
|
|
197
251
|
}
|
|
198
|
-
}else{
|
|
252
|
+
} else {
|
|
199
253
|
// Add current task to list, this is the first one so the primary
|
|
200
|
-
currentTasks[key] = [{queued: new Date()}];
|
|
254
|
+
currentTasks[key] = [{ queued: new Date() }];
|
|
201
255
|
}
|
|
202
256
|
|
|
203
|
-
try{
|
|
204
|
-
if(settings.debug) {
|
|
257
|
+
try {
|
|
258
|
+
if (settings.debug) {
|
|
259
|
+
console.info('[Gorgon] Cache miss, resolving item for: ' + key);
|
|
260
|
+
}
|
|
205
261
|
|
|
206
|
-
// This is the primary item
|
|
207
|
-
const
|
|
262
|
+
// This is the primary item
|
|
263
|
+
const resolver = asyncFunc();
|
|
264
|
+
|
|
265
|
+
gorgonCore._callHooks('get', { key, asyncFunc, policy, cacheHit: false, queued: false }, resolver);
|
|
208
266
|
|
|
209
|
-
|
|
267
|
+
// wait for it to finish then push it out
|
|
268
|
+
const resolvedData = await resolver;
|
|
269
|
+
|
|
270
|
+
if (settings.debug) {
|
|
271
|
+
console.info('[Gorgon] Cache resolved, resolved item for: ' + key, resolvedData);
|
|
272
|
+
}
|
|
210
273
|
|
|
211
274
|
const val = await gorgonCore.put(key, resolvedData, policyMaker(policy));
|
|
212
275
|
|
|
213
276
|
if (hOP.call(currentTasks, key)) {
|
|
214
277
|
for (var i in currentTasks[key]) {
|
|
215
|
-
if(currentTasks[key][i].res) {
|
|
216
|
-
if(settings.debug) {
|
|
278
|
+
if (currentTasks[key][i].res) {
|
|
279
|
+
if (settings.debug) {
|
|
280
|
+
console.info('[Gorgon] Cache queue resolved for: ' + key, resolvedData);
|
|
281
|
+
}
|
|
217
282
|
|
|
218
283
|
currentTasks[key][i].res(val);
|
|
219
284
|
}
|
|
@@ -224,32 +289,29 @@ const Gorgon = (() => {
|
|
|
224
289
|
}
|
|
225
290
|
|
|
226
291
|
return val;
|
|
227
|
-
|
|
228
|
-
}catch (e) {
|
|
292
|
+
} catch (e) {
|
|
229
293
|
if (hOP.call(currentTasks, key)) {
|
|
230
294
|
for (var i in currentTasks[key]) {
|
|
231
|
-
if(currentTasks[key][i].rej) {
|
|
295
|
+
if (currentTasks[key][i].rej) {
|
|
232
296
|
currentTasks[key][i].rej(e);
|
|
233
297
|
}
|
|
234
298
|
}
|
|
235
299
|
|
|
300
|
+
gorgonCore._callHooks('valueError', { key, asyncFunc, policy, cacheHit: false, queued: false }, e);
|
|
301
|
+
|
|
236
302
|
currentTasks[key] = [];
|
|
237
303
|
delete currentTasks[key];
|
|
238
304
|
}
|
|
239
305
|
|
|
240
306
|
throw e;
|
|
241
307
|
}
|
|
242
|
-
|
|
243
308
|
},
|
|
244
|
-
|
|
245
|
-
|
|
246
309
|
};
|
|
247
310
|
|
|
248
311
|
gorgonCore.addProvider('memory', MemoryCache()); // Default provider, light weight and simple
|
|
249
312
|
|
|
250
313
|
return gorgonCore;
|
|
251
|
-
|
|
252
314
|
})();
|
|
253
315
|
|
|
254
|
-
export {MemoryCache};
|
|
316
|
+
export { MemoryCache };
|
|
255
317
|
export default Gorgon;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gorgonjs/gorgon",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A simple caching library for async functions",
|
|
5
5
|
"homepage": "https://gorgonjs.dev",
|
|
6
6
|
"main": "./dist/index.umd.js",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
39
39
|
"@typescript-eslint/parser": "^6.0.0",
|
|
40
40
|
"@vitest/coverage-c8": "^0.25.0",
|
|
41
|
+
"@vitest/coverage-v8": "^0.34.3",
|
|
41
42
|
"eslint": "^8.45.0",
|
|
42
43
|
"jest": "^27.5.1",
|
|
43
44
|
"typescript": "^5.1.6",
|