diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index 5fc2bed2f..2b6867021 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -229,9 +229,9 @@ module.exports = { }, loadKeys_meta: true, - async loadKeys({ conid, database, root, filter }, req) { + async loadKeys({ conid, database, root, filter, limit }, req) { testConnectionPermission(conid, req); - return this.loadDataCore('loadKeys', { conid, database, root, filter }); + return this.loadDataCore('loadKeys', { conid, database, root, filter, limit }); }, exportKeys_meta: true, diff --git a/packages/api/src/proc/databaseConnectionProcess.js b/packages/api/src/proc/databaseConnectionProcess.js index d4a887e9c..840510695 100644 --- a/packages/api/src/proc/databaseConnectionProcess.js +++ b/packages/api/src/proc/databaseConnectionProcess.js @@ -258,8 +258,8 @@ async function handleCollectionData({ msgid, options }) { return handleDriverDataCore(msgid, driver => driver.readCollection(dbhan, options), { logName: 'readCollection' }); } -async function handleLoadKeys({ msgid, root, filter }) { - return handleDriverDataCore(msgid, driver => driver.loadKeys(dbhan, root, filter), { logName: 'loadKeys' }); +async function handleLoadKeys({ msgid, root, filter, limit }) { + return handleDriverDataCore(msgid, driver => driver.loadKeys(dbhan, root, filter, limit), { logName: 'loadKeys' }); } async function handleExportKeys({ msgid, options }) { diff --git a/packages/web/src/widgets/DbKeysSubTree.svelte b/packages/web/src/widgets/DbKeysSubTree.svelte index b5e14b1c9..e82d470b3 100644 --- a/packages/web/src/widgets/DbKeysSubTree.svelte +++ b/packages/web/src/widgets/DbKeysSubTree.svelte @@ -5,7 +5,7 @@ import LoadingInfo from '../elements/LoadingInfo.svelte'; import { apiCall } from '../utility/api'; - const SHOW_INCREMENT = 500; + const SHOW_INCREMENT = 100; import DbKeysTreeNode from './DbKeysTreeNode.svelte'; @@ -20,18 +20,46 @@ export let filter; let reloadToken2 = 0; - let maxShowCount = SHOW_INCREMENT; + let loading = false; + let loadingWhole = false; + let items = []; - // $: items = useDatabaseKeys({ conid, database, root, reloadToken }); + async function loadData() { + loading = true; + const result = await apiCall('database-connections/load-keys', { + conid, + database, + root, + filter, + limit: maxShowCount + 1, + }); + items = result; + loading = false; + loadingWhole = false; + } + + $: { + conid; + database; + root; + filter; + reloadToken; + reloadToken2; + maxShowCount; + loadData(); + } + + $: { + reloadToken; + loadingWhole = true; + } -{#await apiCall('database-connections/load-keys', { conid, database, root, filter, reloadToken, reloadToken2 })} +{#if loadingWhole} -{:then items} - {@const itemsSorted = _.sortBy(items || [], 'text')} - - {#each itemsSorted.slice(0, maxShowCount) as item} +{:else} + {#each items.slice(0, maxShowCount) as item} {/each} - {#if itemsSorted.length > maxShowCount} + {#if loading} + + {:else if items.length > maxShowCount} {/if} -{/await} +{/if} diff --git a/plugins/dbgate-plugin-redis/src/backend/driver.js b/plugins/dbgate-plugin-redis/src/backend/driver.js index d3d119f19..111f24ffb 100644 --- a/plugins/dbgate-plugin-redis/src/backend/driver.js +++ b/plugins/dbgate-plugin-redis/src/backend/driver.js @@ -169,12 +169,14 @@ const driver = { return _.range(16).map((index) => ({ name: `db${index}`, extInfo: info[`db${index}`], sortOrder: index })); }, - async loadKeys(dbhan, root = '', filter = null) { + async loadKeys(dbhan, root = '', filter = null, limit = null) { const keys = await this.getKeys(dbhan, root ? `${root}${dbhan.treeKeySeparator}*` : '*'); const keysFiltered = keys.filter((x) => filterName(filter, x)); - const res = this.extractKeysFromLevel(dbhan, root, keysFiltered); - await this.enrichKeyInfo(dbhan, res); - return res; + const keysSorted = _.sortBy(keysFiltered, 'text'); + const res = this.extractKeysFromLevel(dbhan, root, keysSorted); + const resLimited = limit ? res.slice(0, limit) : res; + await this.enrichKeyInfo(dbhan, resLimited); + return resLimited; }, async exportKeys(dbhan, options) { @@ -192,14 +194,36 @@ const driver = { }, async getKeys(dbhan, keyQuery = '*') { - const res = []; - let cursor = 0; - do { - const [strCursor, keys] = await dbhan.client.scan(cursor, 'MATCH', keyQuery, 'COUNT', 100); - res.push(...keys); - cursor = parseInt(strCursor); - } while (cursor > 0); - return res; + const stream = dbhan.client.scanStream({ + match: keyQuery, + count: 1000, + }); + + const keys = []; + + stream.on('data', (resultKeys) => { + for (const key of resultKeys) { + keys.push(key); + } + }); + + return new Promise((resolve, reject) => { + stream.on('end', () => { + resolve(keys); + }); + stream.on('error', (err) => { + reject(err); + }); + }); + + // const res = []; + // let cursor = 0; + // do { + // const [strCursor, keys] = await dbhan.client.scan(cursor, 'MATCH', keyQuery, 'COUNT', 100); + // res.push(...keys); + // cursor = parseInt(strCursor); + // } while (cursor > 0); + // return res; }, extractKeysFromLevel(dbhan, root, keys) {