import eventBus from '../utils/broadcast-channel-pubsub' export default (name, getObjKey) => { let cache = {}; // update data cached on another node eventBus.on('cache-key-set-' + name, ({key, value}, isLocal) => !isLocal ? set(key, value, false) : null); eventBus.on('cache-all-set' + name, ({data}, isLocal) => !isLocal ? setAll(data, false) : null); eventBus.on('cache-merge-' + name, ({data}, isLocal) => !isLocal ? merge(data, false) : null); eventBus.on('cache-key-forget-' + name, ({key}, isLocal) => !isLocal ? forget(key, false) : null); eventBus.on('cache-flush-' + name, (_, isLocal) => !isLocal ? flush(false) : null); const set = (key, value, emitEvent = true) => { cache[key] = value; if (emitEvent) eventBus.publish('cache-key-set-' + name, {key, value}); return value; }; const setAll = (data, emitEvent = true) => { cache = data; if (emitEvent) eventBus.publish('cache-all-set-' + name, {data}); return cache; } const merge = (data, emitEvent = true) => { cache = {...cache, ...data} if (emitEvent) eventBus.publish('cache-merge-' + name, {data}); return cache; } const get = async (key, fetchFunc) => { if (cache.hasOwnProperty(key)) return cache[key]; const value = await fetchFunc(); return set(key, value); }; const getByFilter = async (fetchFunc, filterFunc) => { if (filterFunc) { const obj = Object.values(cache).find(filterFunc); if (obj) return obj; } const value = await fetchFunc(); if (value === undefined) return value; const key = getObjKey(value); return set(key, value); } const getAll = () => cache; const has = key => cache[key] !== undefined; const getKeys = () => Object.keys(cache); const forget = (key, emitEvent = true) => { delete cache[key]; if (emitEvent) eventBus.publish('cache-key-forget-' + name, {key}); return cache; } const forgetByFilter = (filterFunc, emitEvent = true) => { if (!filterFunc) return false; Object.keys(cache).filter(key => filterFunc(cache[key])) .forEach(key => { delete cache[key] if (emitEvent) eventBus.publish('cache-key-forget-' + name, {key}); }); return true; } const flush = (emitEvent = true) => { cache = {}; if (emitEvent) eventBus.publish('cache-flush-' + name, {}); return cache; } return { has, get, getByFilter, getAll, set, setAll, merge, getKeys, forget, forgetByFilter, flush, } }