diff --git a/cache/MemoryCache.js b/cache/MemoryCache.js index e21103c6..cc8d5949 100644 --- a/cache/MemoryCache.js +++ b/cache/MemoryCache.js @@ -1,7 +1,7 @@ const constants = require("../moduleConstants"); -function MemoryCache() { +function MemoryCache(useWeakRef) { let storage = {}; const self = this; @@ -9,16 +9,24 @@ function MemoryCache() { if(typeof key !== "string"){ throw new Error("Keys should be strings"); } + + let value = storage[key]; + if(value && useWeakRef){ + value = value.deref(); + } if(callback){ - callback(undefined, storage[key]) + callback(undefined, value); } - return storage[key]; + return value; }; self.put = function (key, value, callback) { if(typeof key !== "string"){ throw new Error("Keys should be strings"); } + if(useWeakRef){ + value = value ? new WeakRef(value) : value; + } storage[key] = value; if(callback){ callback(undefined, true) diff --git a/cache/index.js b/cache/index.js index 94c15fca..5819eac1 100644 --- a/cache/index.js +++ b/cache/index.js @@ -30,10 +30,20 @@ function getCacheForVault(storeName, lifetime) { } function getMemoryCache(storeName){ - return stores[storeName] = new MemoryCache(storeName); + return stores[storeName] = new MemoryCache(); +} + +function getWeakRefMemoryCache(storeName){ + let cache = stores[storeName]; + if(!cache){ + cache = new MemoryCache(true); + stores[storeName] = cache; + } + return cache; } module.exports = { getCacheForVault, - getMemoryCache + getMemoryCache, + getWeakRefMemoryCache } \ No newline at end of file diff --git a/resolver/index.js b/resolver/index.js index f33ed0f7..5d89e6a1 100644 --- a/resolver/index.js +++ b/resolver/index.js @@ -3,6 +3,8 @@ const keySSISpace = require("opendsu").loadApi("keyssi"); let {ENVIRONMENT_TYPES, KEY_SSIS} = require("../moduleConstants.js"); const {getWebWorkerBootScript, getNodeWorkerBootScript} = require("./resolver-utils"); +const cache = require("../cache"); +let dsuCache = cache.getWeakRefMemoryCache("mainDSUsCache"); const getResolver = (options) => { options = options || {}; @@ -36,7 +38,13 @@ const createDSU = (templateKeySSI, options, callback) => { } const keySSIResolver = getResolver(options); - keySSIResolver.createDSU(templateKeySSI, options, callback); + keySSIResolver.createDSU(templateKeySSI, options, (err, dsuInstance) => { + if (err) { + return OpenDSUSafeCallback(callback)(createOpenDSUErrorWrapper(`Failed to create DSU instance`, err)); + } + + addDSUInstanceInCache(dsuInstance, callback); + }); }; const createDSUx = (domain, ssiType, options, callback) => { @@ -300,14 +308,36 @@ const loadDSU = (keySSI, options, callback) => { return loadFallbackDSU(keySSI, options, callback); } - const keySSIResolver = getResolver(options); - keySSIResolver.loadDSU(keySSI, options, (err, dsuInstance) => { + const loadDSU = (addInCache) => { + + const keySSIResolver = getResolver(options); + keySSIResolver.loadDSU(keySSI, options, (err, dsuInstance) => { + if (err) { + return OpenDSUSafeCallback(callback)(createOpenDSUErrorWrapper(`Failed to load DSU`, err)); + } + + if (addInCache) { + return addDSUInstanceInCache(dsuInstance, callback); + } + + callback(undefined, dsuInstance); + }); + }; + + if (typeof options === 'object' && options !== null && options.skipCache) { + return loadDSU(false); + } + + keySSI.getAnchorId((err, cacheKey) => { if (err) { - return OpenDSUSafeCallback(callback)(createOpenDSUErrorWrapper(`Failed to load DSU`, err)); + return callback(err); } - - callback(undefined, dsuInstance); - }); + const cachedDSU = dsuCache.get(cacheKey); + if (cachedDSU) { + return getLatestDSUVersion(cachedDSU, callback); + } + loadDSU(true); + }) }; /* @@ -470,10 +500,41 @@ const getRemoteHandler = (dsuKeySSI, remoteURL, presentation) => { }; function invalidateDSUCache(dsuKeySSI, callback) { - //there is a cache at Bar level... - return callback(); + try { + if (typeof dsuKeySSI === "string") { + dsuKeySSI = keySSISpace.parse(dsuKeySSI); + } + } catch (e) { + console.error(e); + } + dsuKeySSI.getAnchorId((err, cacheKey) => { + if (err) { + return callback(err); + } + if (cacheKey) { + delete dsuCache.set(cacheKey, undefined); + } + + callback(); + }); } +function addDSUInstanceInCache(dsuInstance, callback) { + dsuInstance.getKeySSIAsObject((err, keySSI) => { + if (err) { + return OpenDSUSafeCallback(callback)(createOpenDSUErrorWrapper(`Failed to retrieve keySSI`, err)); + } + keySSI.getAnchorId((err, cacheKey) => { + if (err) { + return callback(err); + } + dsuCache.set(cacheKey, dsuInstance); + callback(undefined, dsuInstance); + }); + }); +} + + module.exports = { createDSU, createDSUx, diff --git a/tests/resolver/basic/utils.js b/tests/resolver/basic/utils.js index d018f4f3..5b961d78 100644 --- a/tests/resolver/basic/utils.js +++ b/tests/resolver/basic/utils.js @@ -9,7 +9,7 @@ async function mockEnvironment({ domain, volume, folder } = {}) { const dc = require('double-check'); const cache = require('../../../cache'); - const vault = cache.getCacheForVault('DSUs'); + const vault = cache.getCacheForVault('mainDSUsCache'); if (!domain) { domain = 'default';