diff --git a/backend/services/connection_service.go b/backend/services/connection_service.go index 34e8e66..f0826dc 100644 --- a/backend/services/connection_service.go +++ b/backend/services/connection_service.go @@ -870,22 +870,49 @@ func (c *connectionService) SetKeyTTL(connName string, db int, key string, ttl i } // DeleteKey remove redis key -func (c *connectionService) DeleteKey(connName string, db int, keys []string) (resp types.JSResp) { +func (c *connectionService) DeleteKey(connName string, db int, key string) (resp types.JSResp) { rdb, ctx, err := c.getRedisClient(connName, db) if err != nil { resp.Msg = err.Error() return } + var deletedKeys []string - rmCount, err := rdb.Del(ctx, keys...).Result() - if err != nil { - resp.Msg = err.Error() - return + if strings.HasSuffix(key, "*") { + // delete by prefix + var cursor uint64 + for { + var loadedKey []string + if loadedKey, cursor, err = rdb.Scan(ctx, cursor, key, 10000).Result(); err != nil { + resp.Msg = err.Error() + return + } else { + if err = rdb.Del(ctx, loadedKey...).Err(); err != nil { + resp.Msg = err.Error() + return + } else { + deletedKeys = append(deletedKeys, loadedKey...) + } + } + + // no more loadedKey + if cursor == 0 { + break + } + } + } else { + // delete key only + _, err = rdb.Del(ctx, key).Result() + if err != nil { + resp.Msg = err.Error() + return + } + deletedKeys = append(deletedKeys, key) } resp.Success = true resp.Data = map[string]any{ - "effect_count": rmCount, + "deleted": deletedKeys, } return } diff --git a/frontend/src/components/dialogs/DeleteKeyDialog.vue b/frontend/src/components/dialogs/DeleteKeyDialog.vue index f6e0982..975af49 100644 --- a/frontend/src/components/dialogs/DeleteKeyDialog.vue +++ b/frontend/src/components/dialogs/DeleteKeyDialog.vue @@ -53,7 +53,7 @@ const message = useMessage() const onConfirmDelete = async () => { try { const { server, db, key } = deleteForm - const success = await connectionStore.deleteKeys(server, db, key, deleteForm.affectedKeys) + const success = await connectionStore.deleteKeyPrefix(server, db, key) if (success) { message.success(i18n.t('handle_succ')) } diff --git a/frontend/src/components/sidebar/ConnectionTree.vue b/frontend/src/components/sidebar/ConnectionTree.vue index 46449b4..18c9fc6 100644 --- a/frontend/src/components/sidebar/ConnectionTree.vue +++ b/frontend/src/components/sidebar/ConnectionTree.vue @@ -284,7 +284,7 @@ const findSiblingsAndIndex = (node, nodes) => { } // delay save until stop drop after 2 seconds -const saveSort = debounce(connectionStore.saveConnectionSort, 2000, { trailing: true }) +const saveSort = debounce(connectionStore.saveConnectionSorted, 2000, { trailing: true }) const handleDrop = ({ node, dragNode, dropPosition }) => { const [dragNodeSiblings, dragNodeIndex] = findSiblingsAndIndex(dragNode, connectionStore.connections) if (dragNodeSiblings === null || dragNodeIndex === null) { diff --git a/frontend/src/stores/connections.js b/frontend/src/stores/connections.js index 33f65cd..23721f2 100644 --- a/frontend/src/stores/connections.js +++ b/frontend/src/stores/connections.js @@ -57,12 +57,12 @@ const useConnectionStore = defineStore('connections', { /** * - * @returns {{databases: Object, connections: ConnectionItem[]}} + * @returns {{groups: string[], databases: Object, connections: ConnectionItem[]}} */ state: () => ({ - groups: [], // all group name + groups: [], // all group name set connections: [], // all connections - databases: {}, // all databases in opened connections group by name + databases: {}, // all databases in opened connections group by server name }), getters: { anyConnectionOpened() { @@ -196,10 +196,10 @@ const useConnectionStore = defineStore('connections', { }, /** - * save connection + * save connection after sort * @returns {Promise} */ - async saveConnectionSort() { + async saveConnectionSorted() { const mapToList = (conns) => { const list = [] for (const conn of conns) { @@ -1137,7 +1137,7 @@ const useConnectionStore = defineStore('connections', { */ async deleteKey(connName, db, key) { try { - const { data, success, msg } = await DeleteKey(connName, db, [key]) + const { data, success, msg } = await DeleteKey(connName, db, key) if (success) { // update tree view data this._deleteKeyNode(connName, db, key) @@ -1157,18 +1157,21 @@ const useConnectionStore = defineStore('connections', { * @param connName * @param db * @param prefix - * @param keys * @returns {Promise} */ - async deleteKeys(connName, db, prefix, keys) { - if (isEmpty(keys)) { + async deleteKeyPrefix(connName, db, prefix) { + if (isEmpty(prefix)) { return false } try { - const { success, msg } = await DeleteKey(connName, db, keys) + if (!endsWith(prefix, '*')) { + prefix += '*' + } + const { data, success, msg } = await DeleteKey(connName, db, prefix) if (success) { + const { deleted: keys = [] } = data for (const key of keys) { - await this.deleteKey(connName, db, key) + await this._deleteKeyNode(connName, db, key) await nextTick() } return true