perf: prevent adding new key when value is empty

This commit is contained in:
tiny-craft 2023-07-19 00:50:18 +08:00
parent ab4c78c3d7
commit 00e29ef611
8 changed files with 45 additions and 15 deletions

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"log"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -567,13 +568,9 @@ func (c *connectionService) SetKeyValue(connName string, db int, key, keyType st
return return
} else { } else {
_, err = rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error { _, err = rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {
if len(strs) > 1 {
for _, str := range strs { for _, str := range strs {
pipe.SAdd(ctx, key, str.(string)) pipe.SAdd(ctx, key, str.(string))
} }
} else {
pipe.SAdd(ctx, key)
}
if expiration > 0 { if expiration > 0 {
pipe.Expire(ctx, key, expiration) pipe.Expire(ctx, key, expiration)
} }
@ -585,11 +582,13 @@ func (c *connectionService) SetKeyValue(connName string, db int, key, keyType st
resp.Msg = "invalid zset value" resp.Msg = "invalid zset value"
return return
} else { } else {
log.Println(strs)
_, err = rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error { _, err = rdb.Pipelined(ctx, func(pipe redis.Pipeliner) error {
var members []redis.Z var members []redis.Z
for i := 0; i < len(strs); i += 2 { for i := 0; i < len(strs); i += 2 {
score, _ := strconv.ParseFloat(strs[i].(string), 64)
members = append(members, redis.Z{ members = append(members, redis.Z{
Score: strs[i].(float64), Score: score,
Member: strs[i+1], Member: strs[i+1],
}) })
} }

View File

@ -10,6 +10,7 @@ import NewZSetValue from '../new_value/NewZSetValue.vue'
import NewSetValue from '../new_value/NewSetValue.vue' import NewSetValue from '../new_value/NewSetValue.vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import useConnectionStore from '../../stores/connections.js' import useConnectionStore from '../../stores/connections.js'
import { useMessage } from 'naive-ui'
const i18n = useI18n() const i18n = useI18n()
const newForm = reactive({ const newForm = reactive({
@ -35,6 +36,7 @@ const dbOptions = computed(() =>
})) }))
) )
const newFormRef = ref(null) const newFormRef = ref(null)
const subFormRef = ref(null)
const formLabelWidth = '100px' const formLabelWidth = '100px'
const options = computed(() => { const options = computed(() => {
@ -74,8 +76,15 @@ watch(
) )
const connectionStore = useConnectionStore() const connectionStore = useConnectionStore()
const message = useMessage()
const onAdd = async () => { const onAdd = async () => {
await newFormRef.value?.validate() await newFormRef.value?.validate().catch((err) => {
message.error(err.message)
})
if (subFormRef.value?.validate && !subFormRef.value?.validate()) {
message.error(i18n.t('spec_field_required', { key: i18n.t('element') }))
return false
}
try { try {
const { server, db, key, type, ttl } = newForm const { server, db, key, type, ttl } = newForm
let { value } = newForm let { value } = newForm
@ -145,7 +154,7 @@ const onClose = () => {
<n-button secondary type="primary" @click="newForm.ttl = -1">{{ $t('persist_key') }}</n-button> <n-button secondary type="primary" @click="newForm.ttl = -1">{{ $t('persist_key') }}</n-button>
</n-input-group> </n-input-group>
</n-form-item> </n-form-item>
<component :is="addValueComponent[newForm.type]" v-model:value="newForm.value" /> <component ref="subFormRef" :is="addValueComponent[newForm.type]" v-model:value="newForm.value" />
<!-- TODO: Add import from txt file option --> <!-- TODO: Add import from txt file option -->
</n-form> </n-form>
</n-scrollbar> </n-scrollbar>

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { flatMap, reject } from 'lodash' import { flatMap, isEmpty, reject } from 'lodash'
import Add from '../icons/Add.vue' import Add from '../icons/Add.vue'
import Delete from '../icons/Delete.vue' import Delete from '../icons/Delete.vue'
import IconButton from '../common/IconButton.vue' import IconButton from '../common/IconButton.vue'
@ -28,6 +28,12 @@ const onUpdate = (val) => {
flatMap(val, (item) => [item.key, item.value]) flatMap(val, (item) => [item.key, item.value])
) )
} }
defineExpose({
validate: () => {
return !isEmpty(props.value)
},
})
</script> </script>
<template> <template>

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { compact } from 'lodash' import { compact, isEmpty } from 'lodash'
import Add from '../icons/Add.vue' import Add from '../icons/Add.vue'
import Delete from '../icons/Delete.vue' import Delete from '../icons/Delete.vue'
import IconButton from '../common/IconButton.vue' import IconButton from '../common/IconButton.vue'
@ -15,6 +15,12 @@ const onUpdate = (val) => {
val = compact(val) val = compact(val)
emit('update:value', val) emit('update:value', val)
} }
defineExpose({
validate: () => {
return !isEmpty(props.value)
},
})
</script> </script>
<template> <template>

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { compact, uniq } from 'lodash' import { compact, isEmpty, uniq } from 'lodash'
import Add from '../icons/Add.vue' import Add from '../icons/Add.vue'
import Delete from '../icons/Delete.vue' import Delete from '../icons/Delete.vue'
import IconButton from '../common/IconButton.vue' import IconButton from '../common/IconButton.vue'
@ -15,6 +15,12 @@ const onUpdate = (val) => {
val = uniq(compact(val)) val = uniq(compact(val))
emit('update:value', val) emit('update:value', val)
} }
defineExpose({
validate: () => {
return !isEmpty(props.value)
},
})
</script> </script>
<template> <template>

View File

@ -29,9 +29,15 @@ const onUpdate = () => {
const val = reject(zset.value, (v) => v == null || isEmpty(v.value)) const val = reject(zset.value, (v) => v == null || isEmpty(v.value))
emit( emit(
'update:value', 'update:value',
flatMap(val, (item) => [item.value, item.score]) flatMap(val, (item) => [item.value, item.score.toString()])
) )
} }
defineExpose({
validate: () => {
return !isEmpty(props.value)
},
})
</script> </script>
<template> <template>

View File

@ -128,7 +128,6 @@
"reload_succ": "Reload Success !", "reload_succ": "Reload Success !",
"field_required": "This item should not be blank", "field_required": "This item should not be blank",
"spec_field_required": "\"{key}\" should not be blank", "spec_field_required": "\"{key}\" should not be blank",
"no_connections": "No Connection",
"nonexist_tab_content": "The selected key does not exist. Please retry", "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",

View File

@ -130,7 +130,6 @@
"reload_succ": "已重新载入", "reload_succ": "已重新载入",
"field_required": "此项不能为空", "field_required": "此项不能为空",
"spec_field_required": "{key} 不能为空", "spec_field_required": "{key} 不能为空",
"no_connections": "空空如也",
"nonexist_tab_content": "所选键不存在,请尝试刷新重试", "nonexist_tab_content": "所选键不存在,请尝试刷新重试",
"empty_server_content": "可以从左边选择并打开连接", "empty_server_content": "可以从左边选择并打开连接",
"reload_when_succ": "操作成功后立即重新加载", "reload_when_succ": "操作成功后立即重新加载",