mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-18 00:56:02 +00:00
client metadata caching
This commit is contained in:
@@ -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;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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}`);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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>;
|
||||||
}
|
}
|
||||||
|
|||||||
33
packages/web/src/utility/cache.js
Normal file
33
packages/web/src/utility/cache.js
Normal 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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user