client metadata caching

This commit is contained in:
Jan Prochazka 2020-04-12 20:47:24 +02:00
parent cd645afd00
commit e9c03345c3
8 changed files with 88 additions and 18 deletions

View File

@ -39,14 +39,14 @@ module.exports = {
} else {
res = await this.datastore.insert(connection);
}
socket.emit('connection-list-changed');
socket.emitChanged('connection-list-changed');
return res;
},
delete_meta: 'post',
async delete(connection) {
const res = await this.datastore.remove(_.pick(connection, '_id'));
socket.emit('connection-list-changed');
socket.emitChanged('connection-list-changed');
return res;
},

View File

@ -13,7 +13,7 @@ module.exports = {
const existing = this.opened.find((x) => x.conid == conid && x.database == database);
if (!existing) return;
existing.structure = structure;
socket.emit(`database-structure-changed-${conid}-${database}`);
socket.emitChanged(`database-structure-changed-${conid}-${database}`);
},
handle_error(conid, database, props) {
const { error } = props;

View File

@ -9,7 +9,7 @@ module.exports = {
const existing = this.opened.find(x => x.conid == conid);
if (!existing) return;
existing.databases = databases;
socket.emit(`database-list-changed-${conid}`);
socket.emitChanged(`database-list-changed-${conid}`);
},
handle_error(conid, { error }) {
console.log(`Error in server connection ${conid}: ${error}`);

View File

@ -11,4 +11,9 @@ module.exports = {
console.log('EMIT:', message, data);
socket.emit(message, data);
},
emitChanged(key) {
console.log('EMIT_CHANGED:', key);
socket.emit(key);
socket.emit('clean-cache', key);
}
};

View File

@ -1,6 +1,7 @@
import io from 'socket.io-client';
import React from 'react';
import resolveApi from './resolveApi';
import { cacheClean } from './cache';
const SocketContext = React.createContext(null);
@ -10,6 +11,7 @@ export function SocketProvider({ children }) {
// const newSocket = io('http://localhost:3000', { transports: ['websocket'] });
const newSocket = io(resolveApi());
setSocket(newSocket);
newSocket.on('clean-cache', (reloadTrigger) => cacheClean(reloadTrigger));
}, []);
return <SocketContext.Provider value={socket}>{children}</SocketContext.Provider>;
}

View File

@ -0,0 +1,33 @@
let cachedByKey = {};
let cachedPromisesByKey = {};
const cachedKeysByReloadTrigger = {};
export function cacheGet(key) {
return cachedByKey[key];
}
export function cacheSet(key, value, reloadTrigger) {
cachedByKey[key] = value;
if (!(reloadTrigger in cachedKeysByReloadTrigger)) {
cachedKeysByReloadTrigger[reloadTrigger] = [];
}
cachedKeysByReloadTrigger[reloadTrigger].push(key);
}
export function cacheClean(reloadTrigger) {
const keys = cachedKeysByReloadTrigger[reloadTrigger];
if (keys) {
for (const key of keys) {
delete cachedByKey[key];
delete cachedPromisesByKey[key];
}
}
delete cachedKeysByReloadTrigger[reloadTrigger];
}
export function getCachedPromise(key, func) {
if (key in cachedPromisesByKey) return cachedPromisesByKey[key];
const promise = func();
cachedPromisesByKey[key] = promise;
return promise;
}

View File

@ -1,5 +1,7 @@
import useFetch from './useFetch';
import axios from './axios';
import { cacheGet, cacheSet, getCachedPromise } from './cache';
import stableStringify from 'json-stable-stringify';
const tableInfoLoader = ({ conid, database, schemaName, pureName }) => ({
url: 'metadata/table-info',
@ -9,21 +11,34 @@ const tableInfoLoader = ({ conid, database, schemaName, pureName }) => ({
async function getCore(loader, args) {
const { url, params, reloadTrigger } = loader(args);
const resp = await axios.request({
method: 'get',
url,
params,
});
return resp.data;
const key = stableStringify({ url, ...params });
async function doLoad() {
const resp = await axios.request({
method: 'get',
url,
params,
});
return resp.data;
}
const fromCache = cacheGet(key);
if (fromCache) return fromCache;
const res = getCachedPromise(key, doLoad);
cacheSet(key, res, reloadTrigger);
return res;
}
function useCore(loader, args) {
const { url, params, reloadTrigger } = loader(args);
const cacheKey = stableStringify({ url, ...params });
const res = useFetch({
url,
params,
reloadTrigger,
cacheKey,
});
return res;

View File

@ -3,6 +3,7 @@ import _ from 'lodash';
import axios from './axios';
import useSocket from './SocketProvider';
import stableStringify from 'json-stable-stringify';
import { getCachedPromise, cacheGet, cacheSet } from './cache';
export default function useFetch({
url,
@ -10,6 +11,7 @@ export default function useFetch({
params = undefined,
defaultValue = undefined,
reloadTrigger = undefined,
cacheKey = undefined,
...config
}) {
const [value, setValue] = React.useState([defaultValue, []]);
@ -23,14 +25,27 @@ export default function useFetch({
const indicators = [url, stableStringify(data), stableStringify(params), loadCounter];
async function loadValue(loadedIndicators) {
const resp = await axios.request({
method: 'get',
params,
url,
data,
...config,
});
setValue([resp.data, loadedIndicators]);
async function doLoad() {
const resp = await axios.request({
method: 'get',
params,
url,
data,
...config,
});
return resp.data;
}
if (cacheKey) {
const fromCache = cacheGet(cacheKey);
if (fromCache) return fromCache;
const res = await getCachedPromise(cacheKey, doLoad);
setValue([res, loadedIndicators]);
cacheSet(cacheKey, res, reloadTrigger);
} else {
const res = await doLoad();
setValue([res, loadedIndicators]);
}
}
// React.useEffect(() => {