perf: add non-exists key view
This commit is contained in:
parent
f85b381992
commit
16c096702c
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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": "服务器",
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
Loading…
Reference in New Issue