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 { } else {
res = await this.datastore.insert(connection); res = await this.datastore.insert(connection);
} }
socket.emit('connection-list-changed'); socket.emitChanged('connection-list-changed');
return res; return res;
}, },
delete_meta: 'post', delete_meta: 'post',
async delete(connection) { async delete(connection) {
const res = await this.datastore.remove(_.pick(connection, '_id')); const res = await this.datastore.remove(_.pick(connection, '_id'));
socket.emit('connection-list-changed'); socket.emitChanged('connection-list-changed');
return res; return res;
}, },

View File

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

View File

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

View File

@@ -11,4 +11,9 @@ module.exports = {
console.log('EMIT:', message, data); console.log('EMIT:', message, data);
socket.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 io from 'socket.io-client';
import React from 'react'; import React from 'react';
import resolveApi from './resolveApi'; import resolveApi from './resolveApi';
import { cacheClean } from './cache';
const SocketContext = React.createContext(null); const SocketContext = React.createContext(null);
@@ -10,6 +11,7 @@ export function SocketProvider({ children }) {
// const newSocket = io('http://localhost:3000', { transports: ['websocket'] }); // const newSocket = io('http://localhost:3000', { transports: ['websocket'] });
const newSocket = io(resolveApi()); const newSocket = io(resolveApi());
setSocket(newSocket); setSocket(newSocket);
newSocket.on('clean-cache', (reloadTrigger) => cacheClean(reloadTrigger));
}, []); }, []);
return <SocketContext.Provider value={socket}>{children}</SocketContext.Provider>; 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 useFetch from './useFetch';
import axios from './axios'; import axios from './axios';
import { cacheGet, cacheSet, getCachedPromise } from './cache';
import stableStringify from 'json-stable-stringify';
const tableInfoLoader = ({ conid, database, schemaName, pureName }) => ({ const tableInfoLoader = ({ conid, database, schemaName, pureName }) => ({
url: 'metadata/table-info', url: 'metadata/table-info',
@@ -9,21 +11,34 @@ const tableInfoLoader = ({ conid, database, schemaName, pureName }) => ({
async function getCore(loader, args) { async function getCore(loader, args) {
const { url, params, reloadTrigger } = loader(args); const { url, params, reloadTrigger } = loader(args);
const resp = await axios.request({ const key = stableStringify({ url, ...params });
method: 'get',
url, async function doLoad() {
params, const resp = await axios.request({
}); method: 'get',
return resp.data; 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) { function useCore(loader, args) {
const { url, params, reloadTrigger } = loader(args); const { url, params, reloadTrigger } = loader(args);
const cacheKey = stableStringify({ url, ...params });
const res = useFetch({ const res = useFetch({
url, url,
params, params,
reloadTrigger, reloadTrigger,
cacheKey,
}); });
return res; return res;

View File

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