Skip to content

Commit 7496180

Browse files
committed
chore(indexes): remove in progress only when a matching index shows up in real indexes list; cleanup rolling on a timeout
1 parent 2c24180 commit 7496180

File tree

1 file changed

+64
-5
lines changed

1 file changed

+64
-5
lines changed

packages/compass-indexes/src/modules/regular-indexes.ts

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@ export enum ActionTypes {
101101
IndexCreationStarted = 'compass-indexes/create-index/index-creation-started',
102102
IndexCreationSucceeded = 'compass-indexes/create-index/index-creation-succeeded',
103103
IndexCreationFailed = 'compass-indexes/create-index/index-creation-failed',
104+
105+
// Special case event that happens on a timeout when rolling index is created.
106+
//
107+
// Rolling indexes API doesn't allow us to consistently track whether or not
108+
// creation process failed. This means that in some very rare cases, when
109+
// creating a job to create a rolling index succeeds, but the actual creation
110+
// fails before the index ever shows up in the polled list of indexes, we can
111+
// end up with a stuck "in progress" index. For cases like this we will just
112+
// check whether or not index is still in progress after a few polls and
113+
// remove the in progress index from the list.
114+
RollingIndexTimeoutCheck = 'compass-indexes/create-index/rolling-index-timeout-check',
104115
}
105116

106117
type IndexesOpenedAction = {
@@ -148,6 +159,11 @@ type FailedIndexRemovedAction = {
148159
inProgressIndexId: string;
149160
};
150161

162+
type RollingIndexTimeoutCheckAction = {
163+
type: ActionTypes.RollingIndexTimeoutCheck;
164+
indexId: string;
165+
};
166+
151167
export type State = {
152168
status: FetchStatus;
153169
indexes: RegularIndex[];
@@ -199,10 +215,27 @@ export default function reducer(
199215
ActionTypes.FetchIndexesSucceeded
200216
)
201217
) {
218+
const allIndexNames = new Set(
219+
action.indexes
220+
.map((index) => {
221+
return index.name;
222+
})
223+
.concat(
224+
(action.rollingIndexes ?? []).map((index) => {
225+
return index.indexName;
226+
})
227+
)
228+
);
202229
return {
203230
...state,
204231
indexes: action.indexes,
205232
rollingIndexes: action.rollingIndexes,
233+
// Remove in progress stubs when we got the "real" indexes from one of the
234+
// backends. Keep the error ones around even if the name matches (should
235+
// only be possible in cases of "index with the same name already exists")
236+
inProgressIndexes: state.inProgressIndexes.filter((inProgress) => {
237+
return !!inProgress.error || !allIndexNames.has(inProgress.name);
238+
}),
206239
status: FetchStatuses.READY,
207240
};
208241
}
@@ -243,10 +276,6 @@ export default function reducer(
243276
}
244277

245278
if (
246-
isAction<IndexCreationSucceededAction>(
247-
action,
248-
ActionTypes.IndexCreationSucceeded
249-
) ||
250279
isAction<FailedIndexRemovedAction>(action, ActionTypes.FailedIndexRemoved)
251280
) {
252281
return {
@@ -277,6 +306,27 @@ export default function reducer(
277306
};
278307
}
279308

309+
if (
310+
isAction<RollingIndexTimeoutCheckAction>(
311+
action,
312+
ActionTypes.RollingIndexTimeoutCheck
313+
)
314+
) {
315+
const newInProgressIndexes = state.inProgressIndexes.filter((index) => {
316+
return index.id !== action.indexId;
317+
});
318+
319+
// Nothing was removed, return the previous state to avoid updates
320+
if (newInProgressIndexes.length === state.inProgressIndexes.length) {
321+
return state;
322+
}
323+
324+
return {
325+
...state,
326+
inProgressIndexes: newInProgressIndexes,
327+
};
328+
}
329+
280330
return state;
281331
}
282332

@@ -466,6 +516,7 @@ export function createRegularIndex(
466516
| IndexCreationStartedAction
467517
| IndexCreationSucceededAction
468518
| IndexCreationFailedAction
519+
| RollingIndexTimeoutCheckAction
469520
> {
470521
return async (
471522
dispatch,
@@ -508,7 +559,15 @@ export function createRegularIndex(
508559
await createFn(ns, spec, options);
509560
dispatch(indexCreationSucceeded(inProgressIndexId));
510561
track('Index Created', trackEvent, connectionInfoRef.current);
511-
562+
// See action description for details
563+
if (isRollingIndexBuild) {
564+
setTimeout(() => {
565+
dispatch({
566+
type: ActionTypes.RollingIndexTimeoutCheck,
567+
indexId: inProgressIndexId,
568+
});
569+
}, POLLING_INTERVAL * 3);
570+
}
512571
// Start a new fetch so that the newly added index's details can be
513572
// loaded. indexCreationSucceeded() will remove the in-progress one, but
514573
// we still need the new info.

0 commit comments

Comments
 (0)