From 4fd3d843a771846c7a2fa98a0dc38f92aa7c8c64 Mon Sep 17 00:00:00 2001 From: zalenskiSofteq Date: Thu, 3 Nov 2022 17:00:49 +0100 Subject: [PATCH 1/4] #RI-3764 - List of keys not refreshed after deleting key in redisearch mode --- redisinsight/ui/src/slices/browser/keys.ts | 31 ++++++-- .../ui/src/slices/browser/redisearch.ts | 32 +++++++- .../ui/src/slices/tests/browser/keys.spec.ts | 18 ++--- .../slices/tests/browser/redisearch.spec.ts | 75 +++++++++++++++++++ 4 files changed, 140 insertions(+), 16 deletions(-) diff --git a/redisinsight/ui/src/slices/browser/keys.ts b/redisinsight/ui/src/slices/browser/keys.ts index 0b9c586ca1..2aeab77d59 100644 --- a/redisinsight/ui/src/slices/browser/keys.ts +++ b/redisinsight/ui/src/slices/browser/keys.ts @@ -37,7 +37,7 @@ import { fetchReJSON } from './rejson' import { setHashInitialState, fetchHashFields } from './hash' import { setListInitialState, fetchListElements } from './list' import { fetchStreamEntries, setStreamInitialState } from './stream' -import { fetchMoreRedisearchKeysAction, fetchRedisearchKeysAction, resetRedisearchKeysData, setLastBatchRedisearchKeys, setQueryRedisearch } from './redisearch' +import { deleteRedisearchKeyFromList, editRedisearchKeyFromList, fetchMoreRedisearchKeysAction, fetchRedisearchKeysAction, resetRedisearchKeysData, setLastBatchRedisearchKeys, setQueryRedisearch } from './redisearch' import { addErrorNotification, addMessageNotification } from '../app/notifications' import { KeysStore, KeyViewType, SearchMode } from '../interfaces/keys' import { AppDispatch, RootState } from '../store' @@ -197,7 +197,7 @@ const keysSlice = createSlice({ error: payload, } }, - deleteKeyFromList: (state, { payload }) => { + deletePatternKeyFromList: (state, { payload }) => { remove(state.data?.keys, (key) => isEqualBuffers(key.name, payload)) state.data = { @@ -229,10 +229,11 @@ const keysSlice = createSlice({ error: payload, } }, - editKeyFromList: (state, { payload }) => { + editPatternKeyFromList: (state, { payload }) => { const keys = state.data.keys.map((key) => { if (isEqualBuffers(key.name, payload?.key)) { key.name = payload?.newKey + key.nameString = bufferToString(payload?.newKey) } return key }) @@ -352,8 +353,8 @@ export const { deleteKey, deleteKeySuccess, deleteKeyFailure, - deleteKeyFromList, - editKeyFromList, + deletePatternKeyFromList, + editPatternKeyFromList, updateSelectedKeyLength, setPatternSearchMatch, setFilter, @@ -948,3 +949,23 @@ export function resetKeysData(searchMode: SearchMode) { ? resetPatternKeysData() : resetRedisearchKeysData() } + +export function deleteKeyFromList(key: RedisResponseBuffer) { + return async (dispatch: AppDispatch, stateInit: () => RootState) => { + const state = stateInit() + + return state.browser.keys.searchMode === SearchMode.Pattern + ? dispatch(deletePatternKeyFromList(key)) + : dispatch(deleteRedisearchKeyFromList(key)) + } +} + +export function editKeyFromList(key: RedisResponseBuffer) { + return async (dispatch: AppDispatch, stateInit: () => RootState) => { + const state = stateInit() + + return state.browser.keys.searchMode === SearchMode.Pattern + ? dispatch(editPatternKeyFromList(key)) + : dispatch(editRedisearchKeyFromList(key)) + } +} diff --git a/redisinsight/ui/src/slices/browser/redisearch.ts b/redisinsight/ui/src/slices/browser/redisearch.ts index 3cb4f3e76b..c9ce47e897 100644 --- a/redisinsight/ui/src/slices/browser/redisearch.ts +++ b/redisinsight/ui/src/slices/browser/redisearch.ts @@ -1,10 +1,11 @@ import axios, { AxiosError } from 'axios' import { createSlice, PayloadAction } from '@reduxjs/toolkit' -import successMessages from 'uiSrc/components/notifications/success-messages' +import { remove } from 'lodash' +import successMessages from 'uiSrc/components/notifications/success-messages' import { ApiEndpoints } from 'uiSrc/constants' import { apiService } from 'uiSrc/services' -import { getApiErrorMessage, getUrl, isStatusSuccessful, Nullable } from 'uiSrc/utils' +import { bufferToString, getApiErrorMessage, getUrl, isEqualBuffers, isStatusSuccessful, Nullable } from 'uiSrc/utils' import { DEFAULT_SEARCH_MATCH } from 'uiSrc/constants/api' import { IKeyPropTypes } from 'uiSrc/constants/prop-types/keys' import ApiErrors from 'uiSrc/constants/apiErrors' @@ -150,6 +151,31 @@ const redisearchSlice = createSlice({ resetRedisearchKeysData: (state) => { state.data.keys.length = 0 }, + + deleteRedisearchKeyFromList: (state, { payload }) => { + remove(state.data?.keys, (key) => isEqualBuffers(key.name, payload)) + + state.data = { + ...state.data, + total: state.data.total - 1, + scanned: state.data.scanned - 1, + } + }, + + editRedisearchKeyFromList: (state, { payload }) => { + const keys = state.data.keys.map((key) => { + if (isEqualBuffers(key.name, payload?.key)) { + key.name = payload?.newKey + key.nameString = bufferToString(payload?.newKey) + } + return key + }) + + state.data = { + ...state.data, + keys, + } + }, }, }) @@ -172,6 +198,8 @@ export const { setLastBatchRedisearchKeys, setQueryRedisearch, resetRedisearchKeysData, + deleteRedisearchKeyFromList, + editRedisearchKeyFromList, } = redisearchSlice.actions // Selectors diff --git a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts index 3bd8c8bf9b..5d399b8c8d 100644 --- a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts @@ -42,8 +42,8 @@ import reducer, { deleteKey, deleteKeySuccess, deleteKeyFailure, - deleteKeyFromList, - editKeyFromList, + deletePatternKeyFromList, + editPatternKeyFromList, defaultSelectedKeyActionSuccess, editKey, defaultSelectedKeyActionFailure, @@ -717,7 +717,7 @@ describe('keys slice', () => { }) }) - describe('editKeyFromList', () => { + describe('editPatternKeyFromList', () => { it('should properly set the state before the edit key', () => { // Arrange @@ -740,7 +740,7 @@ describe('keys slice', () => { } // Act - const nextState = reducer(initialStateMock, editKeyFromList(data)) + const nextState = reducer(initialStateMock, editPatternKeyFromList(data)) // Assert const rootState = Object.assign(initialStateDefault, { @@ -1196,7 +1196,7 @@ describe('keys slice', () => { }) describe('deleteKey', () => { - it('call both deleteKey, deleteKeySuccess and deleteKeyFromList when delete is successed', async () => { + it('call both deleteKey, deleteKeySuccess and deletePatternKeyFromList when delete is successed', async () => { // Arrange const data = { name: 'string', @@ -1215,7 +1215,7 @@ describe('keys slice', () => { const expectedActions = [ deleteKey(), deleteKeySuccess(), - deleteKeyFromList(data.name), + deletePatternKeyFromList(data.name), addMessageNotification(successMessages.DELETED_KEY(data.name)), ] expect(store.getActions()).toEqual(expectedActions) @@ -1223,7 +1223,7 @@ describe('keys slice', () => { }) describe('editKey', () => { - it('call both editKey, editKeySuccess and editKeyFromList when editing is successed', async () => { + it('call both editKey, editKeySuccess and editPatternKeyFromList when editing is successed', async () => { // Arrange const key = 'string' const newKey = 'string2' @@ -1235,7 +1235,7 @@ describe('keys slice', () => { await store.dispatch(editKey(key, newKey)) // Assert - const expectedActions = [defaultSelectedKeyAction(), editKeyFromList({ key, newKey })] + const expectedActions = [defaultSelectedKeyAction(), editPatternKeyFromList({ key, newKey })] expect(store.getActions()).toEqual(expectedActions) }) }) @@ -1277,7 +1277,7 @@ describe('keys slice', () => { const expectedActions = [ defaultSelectedKeyAction(), deleteKeySuccess(), - deleteKeyFromList(key), + deletePatternKeyFromList(key), defaultSelectedKeyActionSuccess(), ] expect(store.getActions()).toEqual(expectedActions) diff --git a/redisinsight/ui/src/slices/tests/browser/redisearch.spec.ts b/redisinsight/ui/src/slices/tests/browser/redisearch.spec.ts index 30db768ee5..c5ef3868f9 100644 --- a/redisinsight/ui/src/slices/tests/browser/redisearch.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/redisearch.spec.ts @@ -31,6 +31,8 @@ import reducer, { redisearchSelector, setRedisearchInitialState, resetRedisearchKeysData, + deleteRedisearchKeyFromList, + editRedisearchKeyFromList, } from '../../browser/redisearch' let store: typeof mockedStore @@ -582,6 +584,79 @@ describe('redisearch slice', () => { }) }) + describe('deleteRedisearchKeyFromList', () => { + it('should delete keys from list', () => { + const scanned = 5 + const total = 5 + const strToKey = (name:string) => ({ name: stringToBuffer(name), nameString: name, ttl: 1, size: 1, type: 'hash' }) + + // Arrange + const state = { + ...initialState, + data: { + ...initialState.data, + keys: ['1', '2', '3', '5', '6'].map(strToKey), + scanned: scanned - 1, + total: total - 1 + } + } + + const prevState = { + ...initialState, + data: { + ...initialState.data, + scanned, + total, + keys: ['1', '2', '3', '4', '5', '6'].map(strToKey), + } + } + + // Act + const nextState = reducer(prevState, deleteRedisearchKeyFromList(strToKey('4')?.name)) + + // Assert + const rootState = Object.assign(initialStateDefault, { + browser: { redisearch: nextState }, + }) + expect(redisearchSelector(rootState)).toEqual(state) + }) + }) + + describe('editRedisearchKeyFromList', () => { + it('should rename key in the list', () => { + const strToKey = (name:string) => ({ name: stringToBuffer(name), nameString: name, ttl: 1, size: 1, type: 'hash' }) + + // Arrange + const state = { + ...initialState, + data: { + ...initialState.data, + keys: ['1', '2', '3', '44', '5', '6'].map(strToKey), + } + } + + const prevState = { + ...initialState, + data: { + ...initialState.data, + keys: ['1', '2', '3', '4', '5', '6'].map(strToKey), + } + } + + // Act + const nextState = reducer( + prevState, + editRedisearchKeyFromList({ key: strToKey('4')?.name, newKey: strToKey('44')?.name }), + ) + + // Assert + const rootState = Object.assign(initialStateDefault, { + browser: { redisearch: nextState }, + }) + expect(redisearchSelector(rootState)).toEqual(state) + }) + }) + describe('thunks', () => { describe('fetchRedisearchListAction', () => { it('call both fetchRedisearchListAction, loadListSuccess when fetch is successed', async () => { From 01865add8bf60e174524acb51a4f900ec08b6da8 Mon Sep 17 00:00:00 2001 From: zalenskiSofteq Date: Thu, 3 Nov 2022 17:10:13 +0100 Subject: [PATCH 2/4] #RI-3764 - fix tests --- redisinsight/ui/src/slices/browser/keys.ts | 10 +++++++++- redisinsight/ui/src/slices/tests/browser/keys.spec.ts | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/redisinsight/ui/src/slices/browser/keys.ts b/redisinsight/ui/src/slices/browser/keys.ts index 2aeab77d59..f328302d12 100644 --- a/redisinsight/ui/src/slices/browser/keys.ts +++ b/redisinsight/ui/src/slices/browser/keys.ts @@ -37,7 +37,15 @@ import { fetchReJSON } from './rejson' import { setHashInitialState, fetchHashFields } from './hash' import { setListInitialState, fetchListElements } from './list' import { fetchStreamEntries, setStreamInitialState } from './stream' -import { deleteRedisearchKeyFromList, editRedisearchKeyFromList, fetchMoreRedisearchKeysAction, fetchRedisearchKeysAction, resetRedisearchKeysData, setLastBatchRedisearchKeys, setQueryRedisearch } from './redisearch' +import { + deleteRedisearchKeyFromList, + editRedisearchKeyFromList, + fetchMoreRedisearchKeysAction, + fetchRedisearchKeysAction, + resetRedisearchKeysData, + setLastBatchRedisearchKeys, + setQueryRedisearch, +} from './redisearch' import { addErrorNotification, addMessageNotification } from '../app/notifications' import { KeysStore, KeyViewType, SearchMode } from '../interfaces/keys' import { AppDispatch, RootState } from '../store' diff --git a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts index 5d399b8c8d..d4d0374698 100644 --- a/redisinsight/ui/src/slices/tests/browser/keys.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/keys.spec.ts @@ -735,7 +735,7 @@ describe('keys slice', () => { const state = { ...initialState, data: { - keys: [{ name: data.newKey }], + keys: [{ name: data.newKey, nameString: data.newKey }], }, } From 8e19e62b71a52575ca259c596324c864103fe999 Mon Sep 17 00:00:00 2001 From: zalenskiSofteq Date: Thu, 3 Nov 2022 17:20:16 +0100 Subject: [PATCH 3/4] #RI-3764 - fix tests --- redisinsight/ui/src/slices/browser/keys.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/redisinsight/ui/src/slices/browser/keys.ts b/redisinsight/ui/src/slices/browser/keys.ts index f328302d12..be94264d1b 100644 --- a/redisinsight/ui/src/slices/browser/keys.ts +++ b/redisinsight/ui/src/slices/browser/keys.ts @@ -962,7 +962,7 @@ export function deleteKeyFromList(key: RedisResponseBuffer) { return async (dispatch: AppDispatch, stateInit: () => RootState) => { const state = stateInit() - return state.browser.keys.searchMode === SearchMode.Pattern + return state.browser.keys?.searchMode === SearchMode.Pattern ? dispatch(deletePatternKeyFromList(key)) : dispatch(deleteRedisearchKeyFromList(key)) } @@ -972,7 +972,7 @@ export function editKeyFromList(key: RedisResponseBuffer) { return async (dispatch: AppDispatch, stateInit: () => RootState) => { const state = stateInit() - return state.browser.keys.searchMode === SearchMode.Pattern + return state.browser.keys?.searchMode === SearchMode.Pattern ? dispatch(editPatternKeyFromList(key)) : dispatch(editRedisearchKeyFromList(key)) } From b322a95049c376372ffdd07c7ee24d48910797df Mon Sep 17 00:00:00 2001 From: zalenskiSofteq Date: Thu, 3 Nov 2022 17:43:15 +0100 Subject: [PATCH 4/4] #RI-3764 - fix tests --- redisinsight/ui/src/slices/tests/browser/hash.spec.ts | 4 ++-- redisinsight/ui/src/slices/tests/browser/list.spec.ts | 6 +++--- redisinsight/ui/src/slices/tests/browser/set.spec.ts | 4 ++-- redisinsight/ui/src/slices/tests/browser/zset.spec.ts | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/redisinsight/ui/src/slices/tests/browser/hash.spec.ts b/redisinsight/ui/src/slices/tests/browser/hash.spec.ts index dbf4023f51..7022652149 100644 --- a/redisinsight/ui/src/slices/tests/browser/hash.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/hash.spec.ts @@ -9,11 +9,11 @@ import { } from 'uiSrc/utils/test-utils' import successMessages from 'uiSrc/components/notifications/success-messages' import { bufferToString, stringToBuffer } from 'uiSrc/utils' +import { deleteRedisearchKeyFromList } from 'uiSrc/slices/browser/redisearch' import { defaultSelectedKeyAction, refreshKeyInfo, deleteKeySuccess, - deleteKeyFromList, updateSelectedKeyRefreshTime, } from '../../browser/keys' import reducer, { @@ -642,7 +642,7 @@ describe('hash slice', () => { removeHashFieldsSuccess(), removeFieldsFromList(fields), deleteKeySuccess(), - deleteKeyFromList(key), + deleteRedisearchKeyFromList(key), addMessageNotification(successMessages.DELETED_KEY(key)) ] diff --git a/redisinsight/ui/src/slices/tests/browser/list.spec.ts b/redisinsight/ui/src/slices/tests/browser/list.spec.ts index 7bb2cac625..88ed6d740a 100644 --- a/redisinsight/ui/src/slices/tests/browser/list.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/list.spec.ts @@ -8,11 +8,11 @@ import { mockStore, } from 'uiSrc/utils/test-utils' import successMessages from 'uiSrc/components/notifications/success-messages' -import { DeleteListElementsDto, PushElementToListDto } from 'apiSrc/modules/browser/dto' import { stringToBuffer } from 'uiSrc/utils' +import { deleteRedisearchKeyFromList } from 'uiSrc/slices/browser/redisearch' +import { DeleteListElementsDto, PushElementToListDto } from 'apiSrc/modules/browser/dto' import { defaultSelectedKeyAction, - deleteKeyFromList, deleteKeySuccess, refreshKeyInfo, updateSelectedKeyRefreshTime, @@ -866,7 +866,7 @@ describe('list slice', () => { deleteListElements(), deleteListElementsSuccess(), deleteKeySuccess(), - deleteKeyFromList(data.keyName), + deleteRedisearchKeyFromList(data.keyName), addMessageNotification(successMessages.DELETED_KEY(data.keyName)) ] diff --git a/redisinsight/ui/src/slices/tests/browser/set.spec.ts b/redisinsight/ui/src/slices/tests/browser/set.spec.ts index e60c88ba16..da1ff7f282 100644 --- a/redisinsight/ui/src/slices/tests/browser/set.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/set.spec.ts @@ -10,9 +10,9 @@ import { import { addErrorNotification, addMessageNotification } from 'uiSrc/slices/app/notifications' import successMessages from 'uiSrc/components/notifications/success-messages' import { stringToBuffer } from 'uiSrc/utils' +import { deleteRedisearchKeyFromList } from 'uiSrc/slices/browser/redisearch' import { defaultSelectedKeyAction, - deleteKeyFromList, deleteKeySuccess, refreshKeyInfo, updateSelectedKeyRefreshTime, @@ -675,7 +675,7 @@ describe('set slice', () => { removeSetMembersSuccess(), removeMembersFromList(members), deleteKeySuccess(), - deleteKeyFromList(key), + deleteRedisearchKeyFromList(key), addMessageNotification(successMessages.DELETED_KEY(key)) ] diff --git a/redisinsight/ui/src/slices/tests/browser/zset.spec.ts b/redisinsight/ui/src/slices/tests/browser/zset.spec.ts index 639cc2412e..e2990f7a13 100644 --- a/redisinsight/ui/src/slices/tests/browser/zset.spec.ts +++ b/redisinsight/ui/src/slices/tests/browser/zset.spec.ts @@ -11,10 +11,10 @@ import { import { addErrorNotification, addMessageNotification } from 'uiSrc/slices/app/notifications' import successMessages from 'uiSrc/components/notifications/success-messages' import { stringToBuffer } from 'uiSrc/utils' +import { deleteRedisearchKeyFromList } from 'uiSrc/slices/browser/redisearch' import { AddMembersToZSetDto, ZSetMemberDto } from 'apiSrc/modules/browser/dto' import { defaultSelectedKeyAction, - deleteKeyFromList, deleteKeySuccess, refreshKeyInfo, updateSelectedKeyRefreshTime, @@ -966,7 +966,7 @@ describe('zset slice', () => { removeZsetMembersSuccess(), removeMembersFromList(members), deleteKeySuccess(), - deleteKeyFromList(key), + deleteRedisearchKeyFromList(key), addMessageNotification(successMessages.DELETED_KEY(key)) ]