mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-19 08:26:01 +00:00
cache improvement solves #219
This commit is contained in:
@@ -1,40 +1,120 @@
|
||||
import { apiOn } from './api';
|
||||
import getAsArray from './getAsArray';
|
||||
|
||||
let cachedByKey = {};
|
||||
let cachedPromisesByKey = {};
|
||||
const cachedByKey = {};
|
||||
const cachedPromisesByKey = {};
|
||||
const cachedKeysByReloadTrigger = {};
|
||||
const subscriptionsByReloadTrigger = {};
|
||||
const cacheGenerationByKey = {};
|
||||
|
||||
export function cacheGet(key) {
|
||||
let cacheGeneration = 0;
|
||||
|
||||
function cacheGet(key) {
|
||||
return cachedByKey[key];
|
||||
}
|
||||
|
||||
export function cacheSet(key, value, reloadTrigger) {
|
||||
cachedByKey[key] = value;
|
||||
function addCacheKeyToReloadTrigger(cacheKey, reloadTrigger) {
|
||||
for (const item of getAsArray(reloadTrigger)) {
|
||||
if (!(item in cachedKeysByReloadTrigger)) {
|
||||
cachedKeysByReloadTrigger[item] = [];
|
||||
}
|
||||
cachedKeysByReloadTrigger[item].push(key);
|
||||
cachedKeysByReloadTrigger[item].push(cacheKey);
|
||||
}
|
||||
delete cachedPromisesByKey[key];
|
||||
}
|
||||
|
||||
export function cacheClean(reloadTrigger) {
|
||||
function cacheSet(cacheKey, value, reloadTrigger, generation) {
|
||||
cachedByKey[cacheKey] = value;
|
||||
addCacheKeyToReloadTrigger(cacheKey, reloadTrigger);
|
||||
delete cachedPromisesByKey[cacheKey];
|
||||
cacheGenerationByKey[cacheKey] = generation;
|
||||
}
|
||||
|
||||
function cacheClean(reloadTrigger) {
|
||||
cacheGeneration += 1;
|
||||
for (const item of getAsArray(reloadTrigger)) {
|
||||
const keys = cachedKeysByReloadTrigger[item];
|
||||
if (keys) {
|
||||
for (const key of keys) {
|
||||
delete cachedByKey[key];
|
||||
delete cachedPromisesByKey[key];
|
||||
cacheGenerationByKey[key] = cacheGeneration;
|
||||
}
|
||||
}
|
||||
delete cachedKeysByReloadTrigger[item];
|
||||
}
|
||||
}
|
||||
|
||||
export function getCachedPromise(key, func) {
|
||||
if (key in cachedPromisesByKey) return cachedPromisesByKey[key];
|
||||
function getCachedPromise(reloadTrigger, cacheKey, func) {
|
||||
if (cacheKey in cachedPromisesByKey) return cachedPromisesByKey[cacheKey];
|
||||
const promise = func();
|
||||
cachedPromisesByKey[key] = promise;
|
||||
cachedPromisesByKey[cacheKey] = promise;
|
||||
addCacheKeyToReloadTrigger(cacheKey, reloadTrigger);
|
||||
return promise;
|
||||
}
|
||||
|
||||
function acquireCacheGeneration() {
|
||||
cacheGeneration += 1;
|
||||
return cacheGeneration;
|
||||
}
|
||||
|
||||
function getCacheGenerationForKey(cacheKey) {
|
||||
return cacheGenerationByKey[cacheKey] || 0;
|
||||
}
|
||||
|
||||
export async function loadCachedValue(reloadTrigger, cacheKey, func) {
|
||||
const fromCache = cacheGet(cacheKey);
|
||||
if (fromCache) {
|
||||
return fromCache;
|
||||
} else {
|
||||
const generation = acquireCacheGeneration();
|
||||
try {
|
||||
const res = await getCachedPromise(reloadTrigger, cacheKey, func);
|
||||
if (getCacheGenerationForKey(cacheKey) > generation) {
|
||||
return cacheGet(cacheKey) || res;
|
||||
} else {
|
||||
cacheSet(cacheKey, res, reloadTrigger, generation);
|
||||
return res;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Error when using cached promise', err);
|
||||
cacheClean(cacheKey);
|
||||
const res = await func();
|
||||
cacheSet(cacheKey, res, reloadTrigger, generation);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function subscribeCacheChange(reloadTrigger, cacheKey, reloadHandler) {
|
||||
for (const item of getAsArray(reloadTrigger)) {
|
||||
if (!subscriptionsByReloadTrigger[item]) {
|
||||
subscriptionsByReloadTrigger[item] = [];
|
||||
}
|
||||
subscriptionsByReloadTrigger[item].push(reloadHandler);
|
||||
}
|
||||
}
|
||||
|
||||
export async function unsubscribeCacheChange(reloadTrigger, cacheKey, reloadHandler) {
|
||||
for (const item of getAsArray(reloadTrigger)) {
|
||||
if (subscriptionsByReloadTrigger[item]) {
|
||||
subscriptionsByReloadTrigger[item] = subscriptionsByReloadTrigger[item].filter(x => x != reloadHandler);
|
||||
}
|
||||
if (subscriptionsByReloadTrigger[item].length == 0) {
|
||||
delete subscriptionsByReloadTrigger[item];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dispatchCacheChange(reloadTrigger) {
|
||||
cacheClean(reloadTrigger);
|
||||
|
||||
for (const item of getAsArray(reloadTrigger)) {
|
||||
if (subscriptionsByReloadTrigger[item]) {
|
||||
for (const handler of subscriptionsByReloadTrigger[item]) {
|
||||
handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apiOn('changed-cache', reloadTrigger => dispatchCacheChange(reloadTrigger));
|
||||
|
||||
Reference in New Issue
Block a user