Skip to content

Conversation

valkirilov
Copy link
Member

@valkirilov valkirilov commented Oct 7, 2025

Description

Show the correct command results on the Search and Workbench pages, by filtering out the queries based on the page from which they were executed.

  • make sure we use the feature flag to toggle the data source (Index DB or SQLite) for the Search page as well (like it's done for the Workbench page)
  • show filtered commands when using IndexDB (based on their type, matching the page)
  • show filtered commands when using SQLite (rework the main hook that was responsible to CRUD the history, so it can work for the Search page as well)
  • extended the IndexDB indexes to support easier deletion by type (Search/Workbench), when using the "Clear results" button. It should remove only commands related to the page, not all of them
Screen.Recording.2025-10-07.at.16.36.08.mov
Before After
image image
image image

How it was tested

We have two available ways to store the history of the executed commands - SQLite and IndexDB inside the browser itself.

Using Index DB

Create redisinsight/ui/.env and make sure to put RI_FEATURES_ENV_DEPENDENT_DEFAULT_FLAG=false inside it.

Using SQLite

It's the default mode, but in case you added RI_FEATURES_ENV_DEPENDENT_DEFAULT_FLAG make sure to flip it to true

Reproduction Steps

  1. Go to Databases and open a connection to an existing database instance, ot create a new one
  2. Open the Search page and execute a command inside the code editor (like SEARCH COMMAND)
  3. Go to the Workbench page and execute another command (like WORKBENCH COMMAND)

Switch between the pages and make sure you see the correct commands in the list with the results.

Search Workbench
image image

- makse sure to follow the guidelines defined by the Workbecnh page,
  so do save query results in IndexDB only when the respective feature flag allows it

ire #RI-7602
- filter out the history loaded from the IndexDB, based on the type of the commands,
  so we can show it accordingly to the Search and Workbench pages

re #RI-7602
Copy link
Contributor

github-actions bot commented Oct 7, 2025

Code Coverage - Frontend unit tests

St.
Category Percentage Covered / Total
🟢 Statements 81.97% 19951/24339
🟡 Branches 67.35% 8640/12828
🟡 Functions 75.87% 5296/6980
🟢 Lines 82.39% 19532/23706

Test suite run success

5170 tests passing in 677 suites.

Report generated by 🧪jest coverage report action from e92d15d

- extend the IndexDB indexes to allow easier deletion of records by their type (search/workbench)
- apply the new deletion logic on the search and workbench pages

re #RI-7614

// Step 3: Persist results locally so Vector Search history (CommandsView) shows it
if (Array.isArray(data) && data.length) {
if (envDependentFlag === false && Array.isArray(data) && data.length) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to preserve the commands inside IndexDB always, it should depend on this feature flag, as it's handled in the Workbench.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be done on this layer. Ideally we must always call addCommands and then have a storage strategy based on envDependent flag

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, addCommands is tightly related to wbHistoryStorage, it is not meant to be general solution for command history storage. Internally it uses WorkbenchStorage class, that is writing to IndexedDb.
Same or similar thing can be applied to search history storage. Since it is new implementation, I agree with Artem, that better approach would be an implementation, that takes a useBackendPersistanse = false flag and internally decides how to store the commands, but using addCommands will ALWAYS add these commands to workbench history, which is apparently a problem

})

await addCommands(reverse(data))
if (envDependentFlag === false) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to preserve the commands inside IndexDB always, it should depend on this feature flag, as it's handled in the Workbench.

})
objectStore.createIndex(
CommandExecutionIndex.DatabaseIdType,
['databaseId', 'type'],
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should only remove the records related to the page (Search/Workbench) when clicking the “Clear Results” button. Instead of adding an additional check in the cursor (which iterates over the records while deleting them), I’m introducing a new index that can easily target the correct type.

However, if you find this approach to be incorrect, I can revert to the iterative deletion method.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thinks this is wrong approach. Do not change WorkbenchStorage class to differentiate between storage types, just create vectorSearchHistoryStorage

export const vectorSearchHistoryStorage = new WorkbenchStorage(
  riConfig.app.vectorSearchName,
  2,
)

And if you want to generalize addCommands, getLocalWbHistory etc, modify them to accept the storage instance

const idbIndex = objectStore?.index('dbId')
const indexReq = idbIndex?.openCursor(dbId)
const idbIndex = objectStore?.index(indexName)
const indexReq = idbIndex?.openCursor(indexSelector)
Copy link
Member Author

@valkirilov valkirilov Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, we simply pass the database instance and the type we target (search or workbench), and it will do it.

const idbIndex = objectStore?.index('dbId_type')
const indexReq = idbIndex?.openCursor(['databaseId', 'SEARCH'])

Of course, we still support the old behavior, so you can still target a specific database instance and delete all records related to it.

const idbIndex = objectStore?.index('dbId')
const indexReq = idbIndex?.openCursor('databaseId')

Otherwise, we should delete the records by their type inline, inside the cursor below.

}

return history || []
return history.filter((item) => item.type === commandExecutionType)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we do the magic to apply some filtering, based on the type (Search/Workbench), so we don't show the full history on both pages.

@valkirilov valkirilov self-assigned this Oct 8, 2025
- rework the hooks responsible to keep the commands history
  for the searach page (on desktop) to use the redux store, like the workbench

re #RI-7614

const resultsMode = ResultsMode.Default
const activeRunQueryMode = RunQueryMode.ASCII
const executionType = CommandExecutionType.Search
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, we need to rely on the current implementation for the history manipulation (and automatically switch between SQLite and IndexDB based on the feature flag), so we should go for the existing helpers instead of building them again.

@valkirilov valkirilov marked this pull request as ready for review October 8, 2025 13:35
Comment on lines +31 to +34
const envDependentFlag = useSelector(
(state: RootState) =>
state?.app?.features?.featureFlags?.features?.envDependent?.flag,
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we must return envDependent: { flag: boolean} here and use it below like envdepenent.flag

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we have appFeatureFlagsFeaturesSelector Redux selector, so we can rely on it, or create a new one for this envDependant flag as well. It should be applied to a few more places in the app as well.


// Step 3: Persist results locally so Vector Search history (CommandsView) shows it
if (Array.isArray(data) && data.length) {
if (envDependentFlag === false && Array.isArray(data) && data.length) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be done on this layer. Ideally we must always call addCommands and then have a storage strategy based on envDependent flag


// Step 3: Persist results locally so Vector Search history (CommandsView) shows it
if (Array.isArray(data) && data.length) {
if (envDependentFlag === false && Array.isArray(data) && data.length) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, addCommands is tightly related to wbHistoryStorage, it is not meant to be general solution for command history storage. Internally it uses WorkbenchStorage class, that is writing to IndexedDb.
Same or similar thing can be applied to search history storage. Since it is new implementation, I agree with Artem, that better approach would be an implementation, that takes a useBackendPersistanse = false flag and internally decides how to store the commands, but using addCommands will ALWAYS add these commands to workbench history, which is apparently a problem

})
objectStore.createIndex(
CommandExecutionIndex.DatabaseIdType,
['databaseId', 'type'],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thinks this is wrong approach. Do not change WorkbenchStorage class to differentiate between storage types, just create vectorSearchHistoryStorage

export const vectorSearchHistoryStorage = new WorkbenchStorage(
  riConfig.app.vectorSearchName,
  2,
)

And if you want to generalize addCommands, getLocalWbHistory etc, modify them to accept the storage instance

@valkirilov valkirilov closed this Oct 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants