fix: the deletion result might be incorrect

This commit is contained in:
Lykin 2023-12-26 01:13:21 +08:00
parent 5b9f261824
commit e28bb57a25
6 changed files with 120 additions and 81 deletions

View File

@ -41,7 +41,6 @@
## 未来版本规划
- [ ] 命令实时监控
- [ ] 发布/订阅支持
- [ ] 引入Monaco Editor
- [ ] 连接配置导入/导出
- [ ] 数据导入/导出

View File

@ -504,8 +504,8 @@ func (b *browserService) LoadNextKeys(connName string, db int, match, keyType st
return
}
// LoadAllKeys load all keys
func (b *browserService) LoadAllKeys(connName string, db int, match, keyType string) (resp types.JSResp) {
// LoadNextAllKeys load next all keys
func (b *browserService) LoadNextAllKeys(connName string, db int, match, keyType string) (resp types.JSResp) {
item, err := b.getRedisClient(connName, db)
if err != nil {
resp.Msg = err.Error()
@ -530,6 +530,28 @@ func (b *browserService) LoadAllKeys(connName string, db int, match, keyType str
return
}
// LoadAllKeys load all keys
func (b *browserService) LoadAllKeys(connName string, db int, match, keyType string) (resp types.JSResp) {
item, err := b.getRedisClient(connName, db)
if err != nil {
resp.Msg = err.Error()
return
}
client, ctx := item.client, item.ctx
keys, _, err := b.scanKeys(ctx, client, match, keyType, 0, 0)
if err != nil {
resp.Msg = err.Error()
return
}
resp.Success = true
resp.Data = map[string]any{
"keys": keys,
}
return
}
func (b *browserService) GetKeyType(param types.KeySummaryParam) (resp types.JSResp) {
item, err := b.getRedisClient(param.Server, param.DB)
if err != nil {

View File

@ -47,7 +47,12 @@ const scanAffectedKey = async () => {
try {
loading.value = true
deleteForm.loadingAffected = true
const { keys = [] } = await browserStore.scanKeys(deleteForm.server, deleteForm.db, deleteForm.key)
const { keys = [] } = await browserStore.scanKeys({
server: deleteForm.server,
db: deleteForm.db,
match: deleteForm.key,
loadType: 2,
})
deleteForm.affectedKeys = keys || []
deleteForm.showAffected = true
} finally {

View File

@ -1,4 +1,4 @@
import { isEmpty, remove, sortedIndexBy, sumBy } from 'lodash'
import { isEmpty, remove, sortBy, sortedIndexBy, sumBy } from 'lodash'
import { ConnectionType } from '@/consts/connection_type.js'
/**
@ -74,29 +74,55 @@ export class RedisNodeItem {
* @returns {boolean} return whether key count changed
*/
tidy(skipSort) {
let count = 0
if (!isEmpty(this.children)) {
if (skipSort !== true) {
this._sortNodes(this.children)
}
for (const elem of this.children) {
elem.tidy(skipSort)
count += elem.keyCount
}
} else {
if (this.type === ConnectionType.RedisValue) {
count += 1
if (this.type === ConnectionType.RedisValue) {
this.keyCount = 1
} else if (this.type === ConnectionType.RedisKey || this.type === ConnectionType.RedisDB) {
let keyCount = 0
if (!isEmpty(this.children)) {
if (skipSort !== true) {
this.sortChildren()
}
for (const child of this.children) {
child.tidy(skipSort)
keyCount += child.keyCount
}
} else {
// no children in db node or layer node, set count to 0
count = 0
keyCount = 0
}
if (this.keyCount !== keyCount) {
this.keyCount = keyCount
return true
}
}
if (this.keyCount !== count) {
this.keyCount = count
return true
}
return false
// let count = 0
// if (!isEmpty(this.children)) {
// if (skipSort !== true) {
// this.sortChildren()
// }
//
// for (const elem of this.children) {
// elem.tidy(skipSort)
// count += elem.keyCount
// }
// } else {
// if (this.type === ConnectionType.RedisValue) {
// count += 1
// } else {
// // no children in db node or layer node, set count to 0
// count = 0
// }
// }
// if (this.keyCount !== count) {
// this.keyCount = count
// return true
// }
// return false
}
sortChildren() {
sortBy(this.children, (item) => item.key)
}
/**
@ -123,7 +149,7 @@ export class RedisNodeItem {
}
const removed = remove(this.children, predicate)
if (this.children.length <= 0) {
// remove from parent if no children
// TODO: remove from parent if no children
}
}
@ -131,10 +157,11 @@ export class RedisNodeItem {
return this.children
}
calcKeyCount() {
reCalcKeyCount() {
if (this.type === ConnectionType.RedisValue) {
return 1
this.keyCount = 1
}
return sumBy(this.children, (c) => c.keyCount)
this.keyCount = sumBy(this.children, (c) => c.keyCount)
return this.keyCount
}
}

View File

@ -1,4 +1,4 @@
import { initial, isEmpty, join, last, mapValues, size, slice, sortBy, split, sumBy, toUpper } from 'lodash'
import { initial, isEmpty, join, last, mapValues, size, slice, sortBy, split, toUpper } from 'lodash'
import useConnectionStore from 'stores/connections.js'
import { ConnectionType } from '@/consts/connection_type.js'
import { RedisDatabaseItem } from '@/objects/redisDatabaseItem.js'
@ -79,7 +79,7 @@ export class RedisServerState {
/**
* update max key by increase/decrease value
* @param {string} db
* @param {number} db
* @param {number} updateVal
*/
updateDBKeyCount(db, updateVal) {
@ -309,26 +309,26 @@ export class RedisServerState {
redisKey: key,
})
// check and remove empty layer node
let i = totalParts - 1
for (; i >= 0; i--) {
const anceKey = join(slice(keyParts, 0, i), this.separator)
if (i > 0) {
const anceNode = this.nodeMap.get(`${ConnectionType.RedisKey}/${anceKey}`)
const redisKey = join(slice(keyParts, 0, i + 1), this.separator)
anceNode.removeChild({ type: ConnectionType.RedisKey, redisKey })
if (isEmpty(anceNode.children)) {
this.nodeMap.delete(`${ConnectionType.RedisKey}/${anceKey}`)
} else {
break
}
} else {
// last one, remove from db node
dbRoot.removeChild({ type: ConnectionType.RedisKey, redisKey: keyParts[0] })
this.nodeMap.delete(`${ConnectionType.RedisValue}/${keyParts[0]}`)
}
}
// // check and remove empty layer node
// let i = totalParts - 1
// for (; i >= 0; i--) {
// const anceKey = join(slice(keyParts, 0, i), this.separator)
// if (i > 0) {
// const anceNode = this.nodeMap.get(`${ConnectionType.RedisKey}/${anceKey}`)
// const redisKey = join(slice(keyParts, 0, i + 1), this.separator)
// anceNode.removeChild({ type: ConnectionType.RedisKey, redisKey })
//
// if (isEmpty(anceNode.children)) {
// this.nodeMap.delete(`${ConnectionType.RedisKey}/${anceKey}`)
// } else {
// break
// }
// } else {
// // last one, remove from db node
// dbRoot.removeChild({ type: ConnectionType.RedisKey, redisKey: keyParts[0] })
// this.nodeMap.delete(`${ConnectionType.RedisValue}/${keyParts[0]}`)
// }
// }
}
return true
@ -358,7 +358,6 @@ export class RedisServerState {
node = dbNode
}
const keyCountUpdated = node.tidy(skipResort)
if (keyCountUpdated) {
// update key count of parent and above
for (; i > 0; i--) {
@ -367,16 +366,14 @@ export class RedisServerState {
if (parentNode == null) {
break
}
parentNode.keyCount = parentNode.calcKeyCount()
parentNode.reCalcKeyCount()
}
// update key count of db
// dbNode.keyCount = sumBy(dbNode.children, 'keyCount')
const dbInst = this.databases[this.db]
if (dbInst != null) {
dbInst.keyCount = sumBy(dbNode.children, (c) => c.keyCount)
dbInst.keyCount = dbNode.reCalcKeyCount()
}
}
return true
}
/**

View File

@ -18,6 +18,7 @@ import {
GetKeyType,
GetSlowLogs,
LoadAllKeys,
LoadNextAllKeys,
LoadNextKeys,
OpenConnection,
OpenDatabase,
@ -537,15 +538,22 @@ const useBrowserStore = defineStore('browser', {
* @param {number} db
* @param {string} match
* @param {string} [matchType]
* @param {boolean} [full]
* @param {number} [loadType] 0.load next; 1.load next full; 2.reload load all
* @returns {Promise<{keys: string[], maxKeys: number, end: boolean}>}
*/
async scanKeys(server, db, match, matchType, full) {
async scanKeys({ server, db, match = '*', matchType = '', loadType = 0 }) {
let resp
if (full) {
resp = await LoadAllKeys(server, db, match || '*', matchType)
} else {
resp = await LoadNextKeys(server, db, match || '*', matchType)
switch (loadType) {
case 0:
default:
resp = await LoadNextKeys(server, db, match, matchType)
break
case 1:
resp = await LoadNextAllKeys(server, db, match, matchType)
break
case 2:
resp = await LoadAllKeys(server, db, match, matchType)
break
}
const { data, success, msg } = resp || {}
if (!success) {
@ -575,7 +583,7 @@ const useBrowserStore = defineStore('browser', {
match = prefix + separator + '*'
}
}
return this.scanKeys(server, db, match, matchType, all)
return this.scanKeys({ server, db, match, matchType, loadType: all ? 1 : 0 })
},
/**
@ -1583,25 +1591,6 @@ const useBrowserStore = defineStore('browser', {
// some fail
$message.warn(i18nGlobal.t('dialogue.delete_completed', { success: deletedCount, fail: failCount }))
}
// FIXME: update tree view
// if (!isEmpty(deleted)) {
// let updateDeleted = []
// let count = size(deleted)
// for (const k of deleted) {
// updateDeleted.push(k)
// console.log(count)
// count -= 1
// if (size(updateDeleted) > 100 || count <= 0) {
// for (const dk of updateDeleted) {
// this._deleteKeyNode(server, db, dk, false)
// await nextTick()
// }
// updateDeleted = []
// console.warn('updateDeleted:', updateDeleted)
// }
// }
// }
},
/**