perf: add non-exists key view

This commit is contained in:
tiny-craft 2023-07-10 18:06:14 +08:00
parent f85b381992
commit 16c096702c
5 changed files with 45 additions and 128 deletions

View File

@ -363,6 +363,11 @@ func (c *connectionService) GetKeyValue(connName string, db int, key string) (re
return return
} }
if keyType == "none" {
resp.Msg = "key not exists"
return
}
var ttl int64 var ttl int64
if dur, err = rdb.TTL(ctx, key).Result(); err != nil { if dur, err = rdb.TTL(ctx, key).Result(); err != nil {
ttl = -1 ttl = -1

View File

@ -54,6 +54,18 @@ const onUpdateValue = (tabIndex) => {
tabStore.switchTab(tabIndex) tabStore.switchTab(tabIndex)
} }
/**
* reload current selection key
* @returns {Promise<null>}
*/
const onReloadKey = async () => {
const tab = tabStore.currentTab
if (tab == null || isEmpty(tab.key)) {
return null
}
await connectionStore.loadKeyValue(tab.name, tab.db, tab.key)
}
const i18n = useI18n() const i18n = useI18n()
const confirmDialog = useConfirmDialog() const confirmDialog = useConfirmDialog()
const onCloseTab = (tabIndex) => { const onCloseTab = (tabIndex) => {
@ -81,21 +93,20 @@ const onCloseTab = (tabIndex) => {
<n-ellipsis style="max-width: 150px">{{ t.label }}</n-ellipsis> <n-ellipsis style="max-width: 150px">{{ t.label }}</n-ellipsis>
</n-tab> </n-tab>
</n-tabs> </n-tabs>
<!-- <n-tabs v-model:value="tabStore.activatedIndex" type="line" @update:value="onUpdateValue" :tabs-padding="0">-->
<!-- <n-tab v-for="(t, i) in tab" :key="i" :name="i">-->
<!-- <div class="tab-item flex-box-h">-->
<!-- <div class="tab-item-label ellipsis">-->
<!-- {{ t.label }}-->
<!-- </div>-->
<!-- <n-icon class="tab-item-close" color="gray" size="16" @click.stop="onCloseTab(i)">-->
<!-- <Close :round="false" :stroke-width="5" />-->
<!-- </n-icon>-->
<!-- </div>-->
<!-- </n-tab>-->
<!-- </n-tabs>-->
<!-- TODO: add loading status --> <!-- TODO: add loading status -->
<div v-if="tabContent == null || isEmpty(tabContent.keyPath)" class="flex-item-expand flex-box-v">
<n-empty :description="$t('empty_tab_content')" class="empty-content" />
</div>
<div v-else-if="tabContent.value == null" class="flex-item-expand flex-box-v">
<n-empty :description="$t('nonexist_tab_content')" class="empty-content">
<template #extra>
<n-button @click="onReloadKey">{{ $t('reload') }}</n-button>
</template>
</n-empty>
</div>
<component <component
v-if="tabContent != null && !isEmpty(tabContent.keyPath)" v-else
:is="valueComponents[tabContent.type]" :is="valueComponents[tabContent.type]"
:db="tabContent.db" :db="tabContent.db"
:key-path="tabContent.keyPath" :key-path="tabContent.keyPath"
@ -103,9 +114,6 @@ const onCloseTab = (tabIndex) => {
:ttl="tabContent.ttl" :ttl="tabContent.ttl"
:value="tabContent.value" :value="tabContent.value"
/> />
<div v-else class="flex-item-expand flex-box-v">
<n-empty :description="$t('empty_tab_content')" class="empty-content" />
</div>
</div> </div>
</template> </template>

View File

@ -119,6 +119,7 @@
"spec_field_required": "\"{key}\" should not be blank", "spec_field_required": "\"{key}\" should not be blank",
"no_connections": "No Connection", "no_connections": "No Connection",
"empty_tab_content": "Select the key from left list to see detail.", "empty_tab_content": "Select the key from left list to see detail.",
"nonexist_tab_content": "The selected key does not exist. Please retry",
"empty_server_content": "Connect server from left list", "empty_server_content": "Connect server from left list",
"reload_when_succ": "Reload immediately after success", "reload_when_succ": "Reload immediately after success",
"server": "Server", "server": "Server",

View File

@ -122,6 +122,7 @@
"spec_field_required": "{key} 不能为空", "spec_field_required": "{key} 不能为空",
"no_connections": "空空如也", "no_connections": "空空如也",
"empty_tab_content": "可以从左边选择键来查看键的详细内容", "empty_tab_content": "可以从左边选择键来查看键的详细内容",
"nonexist_tab_content": "所选键不存在,请尝试刷新重试",
"empty_server_content": "可以从左边选择并打开连接", "empty_server_content": "可以从左边选择并打开连接",
"reload_when_succ": "操作成功后立即重新加载", "reload_when_succ": "操作成功后立即重新加载",
"server": "服务器", "server": "服务器",

View File

@ -428,9 +428,9 @@ const useConnectionStore = defineStore('connections', {
async loadKeyValue(server, db, key) { async loadKeyValue(server, db, key) {
try { try {
const { data, success, msg } = await GetKeyValue(server, db, key) const { data, success, msg } = await GetKeyValue(server, db, key)
const tab = useTabStore()
if (success) { if (success) {
const { type, ttl, value } = data const { type, ttl, value } = data
const tab = useTabStore()
tab.upsertTab({ tab.upsertTab({
server, server,
db, db,
@ -440,7 +440,14 @@ const useConnectionStore = defineStore('connections', {
value, value,
}) })
} else { } else {
console.warn('TODO: handle get key fail') tab.upsertTab({
server,
db,
type: 'none',
ttl: -1,
key,
value: null,
})
} }
} finally { } finally {
} }
@ -595,6 +602,9 @@ const useConnectionStore = defineStore('connections', {
* @private * @private
*/ */
_sortNodes(nodeList) { _sortNodes(nodeList) {
if (nodeList == null) {
return
}
nodeList.sort((a, b) => { nodeList.sort((a, b) => {
return a.key > b.key ? 1 : -1 return a.key > b.key ? 1 : -1
}) })
@ -607,8 +617,7 @@ const useConnectionStore = defineStore('connections', {
*/ */
_tidyNodeChildren(node) { _tidyNodeChildren(node) {
let count = 0 let count = 0
const totalChildren = size(node.children) if (!isEmpty(node.children)) {
if (totalChildren > 0) {
this._sortNodes(node.children) this._sortNodes(node.children)
for (const elem of node.children) { for (const elem of node.children) {
@ -621,113 +630,6 @@ const useConnectionStore = defineStore('connections', {
node.keys = count node.keys = count
}, },
/**
* add key to db
* @param {string} connName
* @param {number} db
* @param {string} key
* @private
*/
_addKey(connName, db, key) {
const dbs = this.databases[connName]
const dbDetail = get(dbs, db, {})
if (dbDetail == null) {
return
}
const descendantChain = [dbDetail]
const keyPart = split(key, separator)
let redisKey = ''
const keyLen = size(keyPart)
let added = false
for (let i = 0; i < keyLen; i++) {
redisKey += keyPart[i]
const node = last(descendantChain)
const nodeList = get(node, 'children', [])
const len = size(nodeList)
const isLastKeyPart = i === keyLen - 1
for (let j = 0; j < len + 1; j++) {
const treeKey = get(nodeList[j], 'key')
const isLast = j >= len - 1
const keyType = isLastKeyPart ? ConnectionType.RedisValue : ConnectionType.RedisKey
const curKey = `${connName}/db${db}#${keyType}/${redisKey}`
if (treeKey > curKey || isLast) {
// out of search range, add new item
if (isLastKeyPart) {
// key not exists, add new one
const item = {
key: curKey,
label: keyPart[i],
name: connName,
db,
keys: 1,
redisKey,
type: ConnectionType.RedisValue,
}
if (isLast) {
nodeList.push(item)
} else {
nodeList.splice(j, 0, item)
}
added = true
} else {
// layer not exists, add new one
const item = {
key: curKey,
label: keyPart[i],
name: connName,
db,
keys: 0,
redisKey,
type: ConnectionType.RedisKey,
children: [],
}
if (isLast) {
nodeList.push(item)
descendantChain.push(last(nodeList))
} else {
nodeList.splice(j, 0, item)
descendantChain.push(nodeList[j])
}
redisKey += separator
added = true
}
break
} else if (treeKey === curKey) {
if (isLastKeyPart) {
// same key exists, do nothing
console.log('TODO: same key exist, do nothing now, should replace value later')
} else {
// same group exists, find into it's children
descendantChain.push(nodeList[j])
redisKey += separator
}
break
}
}
}
// update ancestor node's info
if (added) {
const desLen = size(descendantChain)
for (let i = 0; i < desLen; i++) {
const children = get(descendantChain[i], 'children', [])
let keys = 0
for (const child of children) {
if (child.type === ConnectionType.RedisKey) {
keys += get(child, 'keys', 1)
} else if (child.type === ConnectionType.RedisValue) {
keys += get(child, 'keys', 0)
}
}
descendantChain[i].keys = keys
}
}
},
/** /**
* set redis key * set redis key
* @param {string} connName * @param {string} connName
@ -1217,7 +1119,7 @@ const useConnectionStore = defineStore('connections', {
if (success) { if (success) {
// delete old key and add new key struct // delete old key and add new key struct
this._deleteKeyNode(connName, db, key) this._deleteKeyNode(connName, db, key)
this._addKey(connName, db, newKey) this._addKeyNodes(connName, db, [newKey])
return { success: true } return { success: true }
} else { } else {
return { success: false, msg } return { success: false, msg }