-
Notifications
You must be signed in to change notification settings - Fork 230
feat(compass-indexes): add index build progress COMPASS-9495 #7200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds index build progress tracking to the MongoDB Compass indexes table, showing a percentage indicator when indexes are being built. The implementation introduces a new hook for polling index progress via currentOp
command and updates the UI to display build progress and a spinner for in-progress indexes.
- Adds
useIndexProgress
hook for tracking index build progress via polling - Updates Redux state to track progress percentage for in-progress indexes
- Modifies UI components to display progress indicators and spinners for building indexes
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
File | Description |
---|---|
test/setup-store.ts |
Adds mock currentOp method to test data service |
src/stores/store.ts |
Extends data service type to include currentOp for progress tracking |
src/modules/regular-indexes.ts |
Adds progress tracking logic, new actions, and getIndexesProgress thunk |
src/modules/regular-indexes.spec.ts |
Adds tests for index progress tracking functionality |
src/hooks/use-index-progress.ts |
New custom hook for managing index build progress polling |
src/components/regular-indexes-table/regular-indexes-table.tsx |
Integrates progress hook and updates index filtering logic |
src/components/regular-indexes-table/regular-indexes-table.spec.tsx |
Updates tests to mock the progress hook |
src/components/regular-indexes-table/regular-index-actions.tsx |
Adds progress display UI with spinner and percentage |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
packages/compass-indexes/src/components/regular-indexes-table/regular-index-actions.tsx
Outdated
Show resolved
Hide resolved
packages/compass-indexes/src/components/regular-indexes-table/regular-index-actions.tsx
Outdated
Show resolved
Hide resolved
packages/compass-indexes/src/components/regular-indexes-table/in-progress-index-actions.tsx
Outdated
Show resolved
Hide resolved
packages/compass-indexes/src/components/regular-indexes-table/in-progress-index-actions.tsx
Outdated
Show resolved
Hide resolved
packages/compass-indexes/src/components/regular-indexes-table/regular-index-actions.tsx
Outdated
Show resolved
Hide resolved
packages/compass-indexes/src/components/regular-indexes-table/in-progress-index-actions.tsx
Outdated
Show resolved
Hide resolved
packages/compass-indexes/src/components/regular-indexes-table/in-progress-index-actions.tsx
Outdated
Show resolved
Hide resolved
@@ -43,12 +56,27 @@ const IndexActions: React.FunctionComponent<IndexActionsProps> = ({ | |||
[onDeleteFailedIndexClick, index] | |||
); | |||
|
|||
const progress = index.buildProgress * 100; | |||
const isBuilding = progress > 0 && progress < 100; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow this logic, we either have these in "in-progress" bucket or in "regular", how are we expecting this UI to show up for both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps I've over engineered a bit, and I can confirm this again. IIUC the inprogress state is a "fake" one to make the UI show the user's index in the table right away after they create it. It changes to "ready" as soon as we see the index in a listIndexes response. I think the progress logic is left over here from when I would show users 0% when we had a true 0 value. I think I can remove this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, your understanding is totally right here, although I guess now that we actually include in progress in "real" ones, the "in progress" name doesn't make much sense anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't had a chance to track this down, but I'm definitely seeing some weird behaviors locally: if I start the index creation (so it first gets into the "in progress" bucket in the state) I never see the progress shown for it, it just shows "in progress" badge until the index finished building fully, if I look at the indexes for the same collection in a separate tab (so the index is fetched from the beginning, not created as a virtual "in progress" one) it correctly shows the building progress, but the badge shows ready. Screenshots below show how this looks, notice that title_1
is in progress but without the progress in one tab, and ready but with progress in another


if (buildProgress > 0 && buildProgress < 1) { | ||
return ( | ||
<div className={buildProgressStyles} data-testid="index-building-spinner"> | ||
<Body>Building... {(buildProgress * 100) | 0}%</Body> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: we're not using much of bitwise operators in the codebase, can we use truncate here instead for readability?
<Body>Building... {(buildProgress * 100) | 0}%</Body> | |
<Body>Building… {Math.trunc(buildProgress * 100)}%</Body> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
.filter((index) => !rollingIndexNames.has(index.name)) | ||
.filter((index) => !inProgressIndexNames.has(index.name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nit, to avoid two passes
.filter((index) => !rollingIndexNames.has(index.name)) | |
.filter((index) => !inProgressIndexNames.has(index.name)) | |
.filter((index) => !rollingIndexNames.has(index.name) && !inProgressIndexNames.has(index.name)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More than a nit to me, good catch.
Someday we'll use the new Iterator to stack complex set of filters and maps perhaps...
@@ -43,12 +56,27 @@ const IndexActions: React.FunctionComponent<IndexActionsProps> = ({ | |||
[onDeleteFailedIndexClick, index] | |||
); | |||
|
|||
const progress = index.buildProgress * 100; | |||
const isBuilding = progress > 0 && progress < 100; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, your understanding is totally right here, although I guess now that we actually include in progress in "real" ones, the "in progress" name doesn't make much sense anymore
expect(() => screen.getByTestId('index-building-spinner')).to.throw; | ||
expect(() => screen.getByText(/Building\.\.\. \d+%/)).to.throw; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to be called to validate
expect(() => screen.getByTestId('index-building-spinner')).to.throw; | |
expect(() => screen.getByText(/Building\.\.\. \d+%/)).to.throw; | |
expect(() => screen.getByTestId('index-building-spinner')).to.throw(); | |
expect(() => screen.getByText(/Building\.\.\. \d+%/)).to.throw(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, dunno how I missed this. On the node team I recall we either had a lint rule or we monkey-patched this assertion to require it has an argument because you could start throwing something else and not realize.
I am now seeing it display the build percentage correctly by undoing the filtering changes. This does mean the index now has a "ready" badge while there's a "building... x%" string right next to it. Not ideal 🤔 We also have a "building" state but for rolling indexes only, I'm not sure whats the best approach here because it seems like it would be a heavy lift to reframe the statuses from how they are currently used since they're bound to how the UI treats them (like how in-progress is really a dummy state until we get a ping from the server) Any thoughts on the best investments we can make here? Could the status badge also rely on |
Description
Add a percentage to the index build row in the table if it is in progress.
https://jira.mongodb.org/browse/COMPASS-9495
Checklist
Motivation and Context
Open Questions
For reviewers:
useIndexProgress
?getInProgressIndexInfo
used to just list stub indexes because even in progress ones would be listed as "ready" while they continued to build on the server. We now will list "real" indexes via this function. Is that the right approach?Dependents
Types of changes
Screen.Recording.2025-08-15.at.2.29.25.PM.mov
index_finish.mov