From e6b28c9edc4c7de7fd175959bb6febb1fdbce03b Mon Sep 17 00:00:00 2001 From: tiny-craft <137850705+tiny-craft@users.noreply.github.com> Date: Sun, 5 Nov 2023 13:00:03 +0800 Subject: [PATCH] fix: incorrect max keys count after add or delete keys --- backend/services/browser_service.go | 28 ++++++++++++-- frontend/src/stores/browser.js | 57 +++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/backend/services/browser_service.go b/backend/services/browser_service.go index fbbf46b..4daf4cb 100644 --- a/backend/services/browser_service.go +++ b/backend/services/browser_service.go @@ -284,6 +284,25 @@ func (b *browserService) getRedisClient(connName string, db int) (item connectio return } +// load current database size +func (b *browserService) loadDBSize(ctx context.Context, client redis.UniversalClient) int64 { + if cluster, isCluster := client.(*redis.ClusterClient); isCluster { + var keyCount atomic.Int64 + cluster.ForEachMaster(ctx, func(ctx context.Context, cli *redis.Client) error { + if size, serr := cli.DBSize(ctx).Result(); serr != nil { + return serr + } else { + keyCount.Add(size) + } + return nil + }) + return keyCount.Load() + } else { + keyCount, _ := client.DBSize(ctx).Result() + return keyCount + } +} + // save current scan cursor func (b *browserService) setClientCursor(connName string, db int, cursor uint64) { if _, ok := b.connMap[connName]; ok { @@ -433,11 +452,13 @@ func (b *browserService) LoadNextKeys(connName string, db int, match, keyType st return } b.setClientCursor(connName, db, cursor) + maxKeys := b.loadDBSize(ctx, client) resp.Success = true resp.Data = map[string]any{ - "keys": keys, - "end": cursor == 0, + "keys": keys, + "end": cursor == 0, + "maxKeys": maxKeys, } return } @@ -1192,7 +1213,8 @@ func (b *browserService) DeleteKey(connName string, db int, k any, async bool) ( resp.Success = true resp.Data = map[string]any{ - "deleted": deletedKeys, + "deleted": deletedKeys, + "deleteCount": len(deletedKeys), } return } diff --git a/frontend/src/stores/browser.js b/frontend/src/stores/browser.js index 3f7d695..6bf6c2f 100644 --- a/frontend/src/stores/browser.js +++ b/frontend/src/stores/browser.js @@ -1,5 +1,19 @@ import { defineStore } from 'pinia' -import { endsWith, find, get, isEmpty, join, remove, size, slice, sortedIndexBy, split, sumBy, toUpper } from 'lodash' +import { + endsWith, + find, + get, + isEmpty, + join, + remove, + set, + size, + slice, + sortedIndexBy, + split, + sumBy, + toUpper, +} from 'lodash' import { AddHashField, AddListItem, @@ -46,6 +60,7 @@ const useBrowserStore = defineStore('browser', { * @property {string} [redisKey] - redis key, type == ConnectionType.RedisKey || type == ConnectionType.RedisValue only * @property {string} [redisKeyCode] - redis key char code array, optional for redis key which contains binary data * @property {number} [keys] - children key count + * @property {number} [maxKeys] - max key count for database * @property {boolean} [isLeaf] * @property {boolean} [opened] - redis db is opened, type == ConnectionType.RedisDB only * @property {boolean} [expanded] - current node is expanded @@ -257,7 +272,7 @@ const useBrowserStore = defineStore('browser', { if (!success) { throw new Error(msg) } - const { keys = [], end = false } = data + const { keys = [], end = false, maxKeys = 0 } = data const selDB = this.getDatabase(connName, db) if (selDB == null) { return @@ -265,6 +280,7 @@ const useBrowserStore = defineStore('browser', { selDB.opened = true selDB.fullLoaded = end + selDB.maxKeys = maxKeys if (isEmpty(keys)) { selDB.children = [] } else { @@ -732,6 +748,34 @@ const useBrowserStore = defineStore('browser', { return false }, + /** + * update max key by value + * @param {string} connName + * @param {number} db + * @param {number} updateValue + * @private + */ + _updateDBMaxKeys(connName, db, updateValue) { + const database = this.getDatabase(connName, db) + if (database != null) { + const maxKeys = get(database, 'maxKeys', 0) + database.maxKeys = Math.max(0, maxKeys + updateValue) + } + }, + + /** + * set db max keys to 0 + * @param connName + * @param db + * @private + */ + _emptyDBMaxKeys(connName, db) { + const database = this.getDatabase(connName, db) + if (database != null) { + set(database, 'maxKeys', 0) + } + }, + /** * get tree node by key name * @param key @@ -784,6 +828,7 @@ const useBrowserStore = defineStore('browser', { const { newKey = 0 } = this._addKeyNodes(connName, db, [key], true) if (newKey > 0) { this._tidyNode(connName, db, key) + this._updateDBMaxKeys(connName, db, newKey) } return { success, nodeKey: `${connName}/db${db}#${ConnectionType.RedisValue}/${key}` } } else { @@ -1287,14 +1332,17 @@ const useBrowserStore = defineStore('browser', { */ async deleteKey(connName, db, key, soft) { try { + let deleteCount = 0 if (soft !== true) { - await DeleteKey(connName, db, key) + const { data } = await DeleteKey(connName, db, key) + deleteCount = get(data, 'deleteCount', 0) } const k = nativeRedisKey(key) // update tree view data this._deleteKeyNode(connName, db, k) this._tidyNode(connName, db, k, true) + this._updateDBMaxKeys(connName, db, -deleteCount) // set tab content empty const tab = useTabStore() @@ -1327,6 +1375,7 @@ const useBrowserStore = defineStore('browser', { // for (const key of keys) { // await this._deleteKeyNode(connName, db, key) // } + const deleteCount = get(data, 'deleteCount', 0) const separator = this._getSeparator(connName) if (endsWith(prefix, '*')) { prefix = prefix.substring(0, prefix.length - 1) @@ -1336,6 +1385,7 @@ const useBrowserStore = defineStore('browser', { } this._deleteKeyNode(connName, db, prefix, true) this._tidyNode(connName, db, prefix, true) + this._updateDBMaxKeys(connName, db, -deleteCount) return true } } finally { @@ -1357,6 +1407,7 @@ const useBrowserStore = defineStore('browser', { if (success === true) { // update tree view data this._deleteKeyNode(connName, db) + this._emptyDBMaxKeys(connName, db) // set tab content empty const tab = useTabStore() tab.emptyTab(connName)