@@ -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
106117type IndexesOpenedAction = {
@@ -148,6 +159,11 @@ type FailedIndexRemovedAction = {
148159 inProgressIndexId : string ;
149160} ;
150161
162+ type RollingIndexTimeoutCheckAction = {
163+ type : ActionTypes . RollingIndexTimeoutCheck ;
164+ indexId : string ;
165+ } ;
166+
151167export 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