fix: incorrect max keys count after add or delete keys

This commit is contained in:
tiny-craft 2023-11-05 13:00:03 +08:00
parent e28d091500
commit e6b28c9edc
2 changed files with 79 additions and 6 deletions

View File

@ -284,6 +284,25 @@ func (b *browserService) getRedisClient(connName string, db int) (item connectio
return 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 // save current scan cursor
func (b *browserService) setClientCursor(connName string, db int, cursor uint64) { func (b *browserService) setClientCursor(connName string, db int, cursor uint64) {
if _, ok := b.connMap[connName]; ok { if _, ok := b.connMap[connName]; ok {
@ -433,11 +452,13 @@ func (b *browserService) LoadNextKeys(connName string, db int, match, keyType st
return return
} }
b.setClientCursor(connName, db, cursor) b.setClientCursor(connName, db, cursor)
maxKeys := b.loadDBSize(ctx, client)
resp.Success = true resp.Success = true
resp.Data = map[string]any{ resp.Data = map[string]any{
"keys": keys, "keys": keys,
"end": cursor == 0, "end": cursor == 0,
"maxKeys": maxKeys,
} }
return return
} }
@ -1193,6 +1214,7 @@ func (b *browserService) DeleteKey(connName string, db int, k any, async bool) (
resp.Success = true resp.Success = true
resp.Data = map[string]any{ resp.Data = map[string]any{
"deleted": deletedKeys, "deleted": deletedKeys,
"deleteCount": len(deletedKeys),
} }
return return
} }

View File

@ -1,5 +1,19 @@
import { defineStore } from 'pinia' 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 { import {
AddHashField, AddHashField,
AddListItem, AddListItem,
@ -46,6 +60,7 @@ const useBrowserStore = defineStore('browser', {
* @property {string} [redisKey] - redis key, type == ConnectionType.RedisKey || type == ConnectionType.RedisValue only * @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 {string} [redisKeyCode] - redis key char code array, optional for redis key which contains binary data
* @property {number} [keys] - children key count * @property {number} [keys] - children key count
* @property {number} [maxKeys] - max key count for database
* @property {boolean} [isLeaf] * @property {boolean} [isLeaf]
* @property {boolean} [opened] - redis db is opened, type == ConnectionType.RedisDB only * @property {boolean} [opened] - redis db is opened, type == ConnectionType.RedisDB only
* @property {boolean} [expanded] - current node is expanded * @property {boolean} [expanded] - current node is expanded
@ -257,7 +272,7 @@ const useBrowserStore = defineStore('browser', {
if (!success) { if (!success) {
throw new Error(msg) throw new Error(msg)
} }
const { keys = [], end = false } = data const { keys = [], end = false, maxKeys = 0 } = data
const selDB = this.getDatabase(connName, db) const selDB = this.getDatabase(connName, db)
if (selDB == null) { if (selDB == null) {
return return
@ -265,6 +280,7 @@ const useBrowserStore = defineStore('browser', {
selDB.opened = true selDB.opened = true
selDB.fullLoaded = end selDB.fullLoaded = end
selDB.maxKeys = maxKeys
if (isEmpty(keys)) { if (isEmpty(keys)) {
selDB.children = [] selDB.children = []
} else { } else {
@ -732,6 +748,34 @@ const useBrowserStore = defineStore('browser', {
return false 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 * get tree node by key name
* @param key * @param key
@ -784,6 +828,7 @@ const useBrowserStore = defineStore('browser', {
const { newKey = 0 } = this._addKeyNodes(connName, db, [key], true) const { newKey = 0 } = this._addKeyNodes(connName, db, [key], true)
if (newKey > 0) { if (newKey > 0) {
this._tidyNode(connName, db, key) this._tidyNode(connName, db, key)
this._updateDBMaxKeys(connName, db, newKey)
} }
return { success, nodeKey: `${connName}/db${db}#${ConnectionType.RedisValue}/${key}` } return { success, nodeKey: `${connName}/db${db}#${ConnectionType.RedisValue}/${key}` }
} else { } else {
@ -1287,14 +1332,17 @@ const useBrowserStore = defineStore('browser', {
*/ */
async deleteKey(connName, db, key, soft) { async deleteKey(connName, db, key, soft) {
try { try {
let deleteCount = 0
if (soft !== true) { if (soft !== true) {
await DeleteKey(connName, db, key) const { data } = await DeleteKey(connName, db, key)
deleteCount = get(data, 'deleteCount', 0)
} }
const k = nativeRedisKey(key) const k = nativeRedisKey(key)
// update tree view data // update tree view data
this._deleteKeyNode(connName, db, k) this._deleteKeyNode(connName, db, k)
this._tidyNode(connName, db, k, true) this._tidyNode(connName, db, k, true)
this._updateDBMaxKeys(connName, db, -deleteCount)
// set tab content empty // set tab content empty
const tab = useTabStore() const tab = useTabStore()
@ -1327,6 +1375,7 @@ const useBrowserStore = defineStore('browser', {
// for (const key of keys) { // for (const key of keys) {
// await this._deleteKeyNode(connName, db, key) // await this._deleteKeyNode(connName, db, key)
// } // }
const deleteCount = get(data, 'deleteCount', 0)
const separator = this._getSeparator(connName) const separator = this._getSeparator(connName)
if (endsWith(prefix, '*')) { if (endsWith(prefix, '*')) {
prefix = prefix.substring(0, prefix.length - 1) prefix = prefix.substring(0, prefix.length - 1)
@ -1336,6 +1385,7 @@ const useBrowserStore = defineStore('browser', {
} }
this._deleteKeyNode(connName, db, prefix, true) this._deleteKeyNode(connName, db, prefix, true)
this._tidyNode(connName, db, prefix, true) this._tidyNode(connName, db, prefix, true)
this._updateDBMaxKeys(connName, db, -deleteCount)
return true return true
} }
} finally { } finally {
@ -1357,6 +1407,7 @@ const useBrowserStore = defineStore('browser', {
if (success === true) { if (success === true) {
// update tree view data // update tree view data
this._deleteKeyNode(connName, db) this._deleteKeyNode(connName, db)
this._emptyDBMaxKeys(connName, db)
// set tab content empty // set tab content empty
const tab = useTabStore() const tab = useTabStore()
tab.emptyTab(connName) tab.emptyTab(connName)