feat: add flush db operation
This commit is contained in:
parent
67666f4edf
commit
9b9d0e3c7c
|
@ -1521,6 +1521,45 @@ func (c *connectionService) DeleteKey(connName string, db int, k any, async bool
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlushDB flush database
|
||||||
|
func (c *connectionService) FlushDB(connName string, db int, async bool) (resp types.JSResp) {
|
||||||
|
item, err := c.getRedisClient(connName, db)
|
||||||
|
if err != nil {
|
||||||
|
resp.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
flush := func(ctx context.Context, cli redis.UniversalClient) {
|
||||||
|
cli.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
|
||||||
|
pipe.Select(ctx, db)
|
||||||
|
if async {
|
||||||
|
pipe.FlushDBAsync(ctx)
|
||||||
|
} else {
|
||||||
|
pipe.FlushDB(ctx)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
client, ctx := item.client, item.ctx
|
||||||
|
if cluster, ok := client.(*redis.ClusterClient); ok {
|
||||||
|
// cluster mode
|
||||||
|
err = cluster.ForEachMaster(ctx, func(ctx context.Context, cli *redis.Client) error {
|
||||||
|
flush(ctx, cli)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
flush(ctx, client)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
resp.Msg = err.Error()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.Success = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// RenameKey rename key
|
// RenameKey rename key
|
||||||
func (c *connectionService) RenameKey(connName string, db int, key, newKey string) (resp types.JSResp) {
|
func (c *connectionService) RenameKey(connName string, db int, key, newKey string) (resp types.JSResp) {
|
||||||
item, err := c.getRedisClient(connName, db)
|
item, err := c.getRedisClient(connName, db)
|
||||||
|
|
|
@ -99,7 +99,7 @@ func (l *LogHook) ProcessPipelineHook(next redis.ProcessPipelineHook) redis.Proc
|
||||||
err := next(ctx, cmds)
|
err := next(ctx, cmds)
|
||||||
cost := time.Since(t).Milliseconds()
|
cost := time.Since(t).Milliseconds()
|
||||||
b := make([]byte, 0, 64)
|
b := make([]byte, 0, 64)
|
||||||
for _, cmd := range cmds {
|
for i, cmd := range cmds {
|
||||||
log.Println("pipeline: ", cmd)
|
log.Println("pipeline: ", cmd)
|
||||||
if l.cmdExec != nil {
|
if l.cmdExec != nil {
|
||||||
for i, arg := range cmd.Args() {
|
for i, arg := range cmd.Args() {
|
||||||
|
@ -108,7 +108,9 @@ func (l *LogHook) ProcessPipelineHook(next redis.ProcessPipelineHook) redis.Proc
|
||||||
}
|
}
|
||||||
b = appendArg(b, arg)
|
b = appendArg(b, arg)
|
||||||
}
|
}
|
||||||
b = append(b, '\n')
|
if i != len(cmds) {
|
||||||
|
b = append(b, '\n')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if l.cmdExec != nil {
|
if l.cmdExec != nil {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import KeyFilterDialog from './components/dialogs/KeyFilterDialog.vue'
|
||||||
import { WindowSetDarkTheme, WindowSetLightTheme } from 'wailsjs/runtime/runtime.js'
|
import { WindowSetDarkTheme, WindowSetLightTheme } from 'wailsjs/runtime/runtime.js'
|
||||||
import { darkThemeOverrides, themeOverrides } from '@/utils/theme.js'
|
import { darkThemeOverrides, themeOverrides } from '@/utils/theme.js'
|
||||||
import AboutDialog from '@/components/dialogs/AboutDialog.vue'
|
import AboutDialog from '@/components/dialogs/AboutDialog.vue'
|
||||||
|
import FlushDbDialog from '@/components/dialogs/FlushDbDialog.vue'
|
||||||
|
|
||||||
hljs.registerLanguage('json', json)
|
hljs.registerLanguage('json', json)
|
||||||
hljs.registerLanguage('plaintext', plaintext)
|
hljs.registerLanguage('plaintext', plaintext)
|
||||||
|
@ -73,6 +74,7 @@ watch(
|
||||||
<add-fields-dialog />
|
<add-fields-dialog />
|
||||||
<rename-key-dialog />
|
<rename-key-dialog />
|
||||||
<delete-key-dialog />
|
<delete-key-dialog />
|
||||||
|
<flush-db-dialog />
|
||||||
<set-ttl-dialog />
|
<set-ttl-dialog />
|
||||||
<preferences-dialog />
|
<preferences-dialog />
|
||||||
<about-dialog />
|
<about-dialog />
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, nextTick, reactive, ref } from 'vue'
|
import { computed, h, nextTick, reactive, ref } from 'vue'
|
||||||
import IconButton from '@/components/common/IconButton.vue'
|
import IconButton from '@/components/common/IconButton.vue'
|
||||||
import Refresh from '@/components/icons/Refresh.vue'
|
import Refresh from '@/components/icons/Refresh.vue'
|
||||||
import useConnectionStore from 'stores/connections.js'
|
import useConnectionStore from 'stores/connections.js'
|
||||||
import { map, uniqBy } from 'lodash'
|
import { map, size, split, uniqBy } from 'lodash'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import Delete from '@/components/icons/Delete.vue'
|
import Delete from '@/components/icons/Delete.vue'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
@ -132,6 +132,17 @@ defineExpose({
|
||||||
filter(value, row) {
|
filter(value, row) {
|
||||||
return value === '' || !!~row.cmd.indexOf(value.toString())
|
return value === '' || !!~row.cmd.indexOf(value.toString())
|
||||||
},
|
},
|
||||||
|
render({ cmd }, index) {
|
||||||
|
const cmdList = split(cmd, '\n')
|
||||||
|
if (size(cmdList) > 1) {
|
||||||
|
return h(
|
||||||
|
'div',
|
||||||
|
null,
|
||||||
|
map(cmdList, (c) => h('div', null, c)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: $t('log.cost_time'),
|
title: $t('log.cost_time'),
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<script setup>
|
||||||
|
import { reactive, watch } from 'vue'
|
||||||
|
import useDialog from 'stores/dialog'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import useConnectionStore from 'stores/connections.js'
|
||||||
|
|
||||||
|
const flushForm = reactive({
|
||||||
|
server: '',
|
||||||
|
db: 0,
|
||||||
|
key: '',
|
||||||
|
async: false,
|
||||||
|
confirm: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialogStore = useDialog()
|
||||||
|
const connectionStore = useConnectionStore()
|
||||||
|
watch(
|
||||||
|
() => dialogStore.flushDBDialogVisible,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
const { server, db } = dialogStore.flushDBParam
|
||||||
|
flushForm.server = server
|
||||||
|
flushForm.db = db
|
||||||
|
flushForm.async = true
|
||||||
|
flushForm.confirm = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const i18n = useI18n()
|
||||||
|
const onConfirmFlush = async () => {
|
||||||
|
try {
|
||||||
|
const { server, db, async } = flushForm
|
||||||
|
const success = await connectionStore.flushDatabase(server, db, async)
|
||||||
|
if (success) {
|
||||||
|
$message.success(i18n.t('dialogue.handle_succ'))
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
$message.error(e.message)
|
||||||
|
}
|
||||||
|
dialogStore.closeFlushDBDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
dialogStore.closeFlushDBDialog()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<n-modal
|
||||||
|
v-model:show="dialogStore.flushDBDialogVisible"
|
||||||
|
:closable="false"
|
||||||
|
:close-on-esc="false"
|
||||||
|
:mask-closable="false"
|
||||||
|
:show-icon="false"
|
||||||
|
:title="$t('interface.flush_db')"
|
||||||
|
preset="dialog"
|
||||||
|
transform-origin="center">
|
||||||
|
<n-form :model="flushForm" :show-require-mark="false" label-placement="top">
|
||||||
|
<n-form-item :label="$t('dialogue.key.server')">
|
||||||
|
<n-input :value="flushForm.server" readonly />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item :label="$t('dialogue.key.db_index')">
|
||||||
|
<n-input :value="flushForm.db.toString()" readonly />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item :label="$t('dialogue.key.async_delete')" required>
|
||||||
|
<n-checkbox v-model:checked="flushForm.async">{{ $t('dialogue.key.async_delete_title') }}</n-checkbox>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item :label="$t('common.warning')" required>
|
||||||
|
<n-checkbox v-model:checked="flushForm.confirm">
|
||||||
|
<span style="color: red; font-weight: bold">{{ $t('dialogue.key.confirm_flush') }}</span>
|
||||||
|
</n-checkbox>
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
|
||||||
|
<template #action>
|
||||||
|
<n-button :focusable="false" @click="onClose">{{ $t('common.cancel') }}</n-button>
|
||||||
|
<n-button :disabled="!!!flushForm.confirm" :focusable="false" type="primary" @click="onConfirmFlush">
|
||||||
|
{{ $t('dialogue.key.confirm_flush_db') }}
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
</n-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
|
@ -10,7 +10,7 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
strokeColor: {
|
strokeColor: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '#FFF',
|
default: 'currentColor',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -117,8 +117,8 @@ const menuOptions = {
|
||||||
key: 'd1',
|
key: 'd1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'key_remove',
|
key: 'db_flush',
|
||||||
label: i18n.t('interface.batch_delete'),
|
label: i18n.t('interface.flush_db'),
|
||||||
icon: renderIcon(Delete),
|
icon: renderIcon(Delete),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -163,7 +163,7 @@ const menuOptions = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'key_remove',
|
key: 'key_remove',
|
||||||
label: i18n.t('interface.batch_delete'),
|
label: i18n.t('interface.batch_delete_key'),
|
||||||
icon: renderIcon(Delete),
|
icon: renderIcon(Delete),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -260,7 +260,7 @@ const handleSelectContextMenu = (key) => {
|
||||||
connectionStore.closeDatabase(props.server, db)
|
connectionStore.closeDatabase(props.server, db)
|
||||||
break
|
break
|
||||||
case 'db_flush':
|
case 'db_flush':
|
||||||
dialogStore.openDeleteKeyDialog(props.server, db, '*')
|
dialogStore.openFlushDBDialog(props.server, db)
|
||||||
break
|
break
|
||||||
case 'db_newkey':
|
case 'db_newkey':
|
||||||
case 'key_newkey':
|
case 'key_newkey':
|
||||||
|
@ -548,7 +548,7 @@ const getDatabaseMenu = (opened, loading, end) => {
|
||||||
onClick: () => handleSelectContextMenu('db_loadall'),
|
onClick: () => handleSelectContextMenu('db_loadall'),
|
||||||
}),
|
}),
|
||||||
h(IconButton, {
|
h(IconButton, {
|
||||||
tTooltip: 'interface.batch_delete',
|
tTooltip: 'interface.flush_db',
|
||||||
icon: Delete,
|
icon: Delete,
|
||||||
disabled: loading === true,
|
disabled: loading === true,
|
||||||
onClick: () => handleSelectContextMenu('db_flush'),
|
onClick: () => handleSelectContextMenu('db_flush'),
|
||||||
|
@ -585,7 +585,7 @@ const getLayerMenu = () => {
|
||||||
onClick: () => handleSelectContextMenu('key_newkey'),
|
onClick: () => handleSelectContextMenu('key_newkey'),
|
||||||
}),
|
}),
|
||||||
h(IconButton, {
|
h(IconButton, {
|
||||||
tTooltip: 'interface.batch_delete',
|
tTooltip: 'interface.batch_delete_key',
|
||||||
icon: Delete,
|
icon: Delete,
|
||||||
onClick: () => handleSelectContextMenu('key_remove'),
|
onClick: () => handleSelectContextMenu('key_remove'),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
"rename_key": "Rename Key",
|
"rename_key": "Rename Key",
|
||||||
"delete_key": "Delete Key",
|
"delete_key": "Delete Key",
|
||||||
"batch_delete_key": "Batch Delete Keys",
|
"batch_delete_key": "Batch Delete Keys",
|
||||||
|
"flush_db": "Flush Database",
|
||||||
"copy_value": "Copy Value",
|
"copy_value": "Copy Value",
|
||||||
"edit_value": "Edit Value",
|
"edit_value": "Edit Value",
|
||||||
"save_update": "Save Update",
|
"save_update": "Save Update",
|
||||||
|
@ -82,7 +83,6 @@
|
||||||
"decode_with": "Decode / Decompression",
|
"decode_with": "Decode / Decompression",
|
||||||
"reload": "Reload",
|
"reload": "Reload",
|
||||||
"open_connection": "Open Connection",
|
"open_connection": "Open Connection",
|
||||||
"batch_delete": "Batch Delete",
|
|
||||||
"copy_path": "Copy Path",
|
"copy_path": "Copy Path",
|
||||||
"copy_key": "Copy Key",
|
"copy_key": "Copy Key",
|
||||||
"binary_key": "Binary Key Name",
|
"binary_key": "Binary Key Name",
|
||||||
|
@ -214,14 +214,16 @@
|
||||||
"new": "New Key",
|
"new": "New Key",
|
||||||
"new_name": "New Key Name",
|
"new_name": "New Key Name",
|
||||||
"persist_key": "Persist Key",
|
"persist_key": "Persist Key",
|
||||||
"server": "Belong",
|
"server": "Connection",
|
||||||
"db_index": "Database Index",
|
"db_index": "Database Index",
|
||||||
"key_expression": "Key Expression",
|
"key_expression": "Key Expression",
|
||||||
"affected_key": "Affected Keys",
|
"affected_key": "Affected Keys",
|
||||||
"show_affected_key": "Show Affected Keys",
|
"show_affected_key": "Show Affected Keys",
|
||||||
"confirm_delete_key": "Confirm Delete {num} Key(s)",
|
"confirm_delete_key": "Confirm Delete {num} Key(s)",
|
||||||
"async_delete": "Asynchronously Execute",
|
"async_delete": "Asynchronously Execute",
|
||||||
"async_delete_title": "Do not waiting for the operation's result"
|
"async_delete_title": "Do not waiting for the operation's result",
|
||||||
|
"confirm_flush": "I know what I'm doing!",
|
||||||
|
"confirm_flush_db": "Confirm Flush Database"
|
||||||
},
|
},
|
||||||
"field": {
|
"field": {
|
||||||
"new": "Add New Field",
|
"new": "Add New Field",
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
"rename_key": "重命名键",
|
"rename_key": "重命名键",
|
||||||
"delete_key": "删除键",
|
"delete_key": "删除键",
|
||||||
"batch_delete_key": "批量删除键",
|
"batch_delete_key": "批量删除键",
|
||||||
|
"flush_db": "清空数据库",
|
||||||
"copy_value": "复制值",
|
"copy_value": "复制值",
|
||||||
"edit_value": "修改值",
|
"edit_value": "修改值",
|
||||||
"save_update": "保存修改",
|
"save_update": "保存修改",
|
||||||
|
@ -82,7 +83,6 @@
|
||||||
"decode_with": "解码/解压方式",
|
"decode_with": "解码/解压方式",
|
||||||
"reload": "重新载入",
|
"reload": "重新载入",
|
||||||
"open_connection": "打开连接",
|
"open_connection": "打开连接",
|
||||||
"batch_delete": "批量删除键",
|
|
||||||
"copy_path": "复制路径",
|
"copy_path": "复制路径",
|
||||||
"copy_key": "复制键名",
|
"copy_key": "复制键名",
|
||||||
"binary_key": "二进制键名",
|
"binary_key": "二进制键名",
|
||||||
|
@ -220,7 +220,9 @@
|
||||||
"show_affected_key": "查看受影响的键名",
|
"show_affected_key": "查看受影响的键名",
|
||||||
"confirm_delete_key": "确认删除{num}个键",
|
"confirm_delete_key": "确认删除{num}个键",
|
||||||
"async_delete": "异步执行",
|
"async_delete": "异步执行",
|
||||||
"async_delete_title": "不等待操作结果"
|
"async_delete_title": "不等待操作结果",
|
||||||
|
"confirm_flush": "我知道我正在执行的操作!",
|
||||||
|
"confirm_flush_db": "确认清空数据库"
|
||||||
},
|
},
|
||||||
"field": {
|
"field": {
|
||||||
"new": "添加新字段",
|
"new": "添加新字段",
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
DeleteConnection,
|
DeleteConnection,
|
||||||
DeleteGroup,
|
DeleteGroup,
|
||||||
DeleteKey,
|
DeleteKey,
|
||||||
|
FlushDB,
|
||||||
GetCmdHistory,
|
GetCmdHistory,
|
||||||
GetConnection,
|
GetConnection,
|
||||||
GetKeyValue,
|
GetKeyValue,
|
||||||
|
@ -1666,6 +1667,30 @@ const useConnectionStore = defineStore('connections', {
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flush database
|
||||||
|
* @param connName
|
||||||
|
* @param db
|
||||||
|
* @param async
|
||||||
|
* @return {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
async flushDatabase(connName, db, async) {
|
||||||
|
try {
|
||||||
|
const { success = false } = await FlushDB(connName, db, async)
|
||||||
|
|
||||||
|
if (success === true) {
|
||||||
|
// update tree view data
|
||||||
|
this._deleteKeyNode(connName, db)
|
||||||
|
// set tab content empty
|
||||||
|
const tab = useTabStore()
|
||||||
|
tab.emptyTab(connName)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rename key
|
* rename key
|
||||||
* @param {string} connName
|
* @param {string} connName
|
||||||
|
|
|
@ -63,6 +63,12 @@ const useDialogStore = defineStore('dialog', {
|
||||||
},
|
},
|
||||||
deleteKeyDialogVisible: false,
|
deleteKeyDialogVisible: false,
|
||||||
|
|
||||||
|
flushDBParam: {
|
||||||
|
server: '',
|
||||||
|
db: 0,
|
||||||
|
},
|
||||||
|
flushDBDialogVisible: false,
|
||||||
|
|
||||||
selectTTL: -1,
|
selectTTL: -1,
|
||||||
ttlDialogVisible: false,
|
ttlDialogVisible: false,
|
||||||
|
|
||||||
|
@ -164,6 +170,15 @@ const useDialogStore = defineStore('dialog', {
|
||||||
this.deleteKeyDialogVisible = false
|
this.deleteKeyDialogVisible = false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
openFlushDBDialog(server, db) {
|
||||||
|
this.flushDBParam.server = server
|
||||||
|
this.flushDBParam.db = db
|
||||||
|
this.flushDBDialogVisible = true
|
||||||
|
},
|
||||||
|
closeFlushDBDialog() {
|
||||||
|
this.flushDBDialogVisible = false
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} prefix
|
* @param {string} prefix
|
||||||
|
|
Loading…
Reference in New Issue