Skip to content

Commit abc14f5

Browse files
[Upgrade Assistant] Open And Close Slight Refactor (#59890)
* Refactor: Move checking of closed index to single point We should rather only check if an index is currently closed the moment before starting to reindex. We still store a flag to indicate that we opened an index that was closed, but this should not be set from the reindex handlers because the reindex task may only start some time later in which case the closed index could have been opened and our reindex job will open it and close it again. * Added debug log * Added comment Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent d5c0928 commit abc14f5

File tree

7 files changed

+41
-33
lines changed

7 files changed

+41
-33
lines changed

x-pack/plugins/upgrade_assistant/server/lib/es_indices_state_check.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,24 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import { IScopedClusterClient } from 'kibana/server';
7+
import { APICaller } from 'kibana/server';
88
import { getIndexStateFromClusterState } from '../../common/get_index_state_from_cluster_state';
99
import { ClusterStateAPIResponse } from '../../common/types';
1010

1111
type StatusCheckResult = Record<string, 'open' | 'close'>;
1212

1313
export const esIndicesStateCheck = async (
14-
dataClient: IScopedClusterClient,
14+
callAsUser: APICaller,
1515
indices: string[]
1616
): Promise<StatusCheckResult> => {
1717
// According to https://www.elastic.co/guide/en/elasticsearch/reference/7.6/cluster-state.html
1818
// The response from this call is considered internal and subject to change. We have an API
1919
// integration test for asserting that the current ES version still returns what we expect.
2020
// This lives in x-pack/test/upgrade_assistant_integration
21-
const clusterState: ClusterStateAPIResponse = await dataClient.callAsCurrentUser(
22-
'cluster.state',
23-
{
24-
index: indices,
25-
metric: 'metadata',
26-
}
27-
);
21+
const clusterState: ClusterStateAPIResponse = await callAsUser('cluster.state', {
22+
index: indices,
23+
metric: 'metadata',
24+
});
2825

2926
const result: StatusCheckResult = {};
3027

x-pack/plugins/upgrade_assistant/server/lib/es_migration_apis.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ export async function getUpgradeAssistantStatus(
2727
// If we have found deprecation information for index/indices check whether the index is
2828
// open or closed.
2929
if (indexNames.length) {
30-
const indexStates = await esIndicesStateCheck(dataClient, indexNames);
30+
const indexStates = await esIndicesStateCheck(
31+
dataClient.callAsCurrentUser.bind(dataClient),
32+
indexNames
33+
);
3134

3235
indices.forEach(indexData => {
3336
indexData.blockerForReindexing =

x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* or more contributor license agreements. Licensed under the Elastic License;
44
* you may not use this file except in compliance with the Elastic License.
55
*/
6-
6+
jest.mock('../es_indices_state_check', () => ({ esIndicesStateCheck: jest.fn() }));
77
import { BehaviorSubject } from 'rxjs';
88
import { Logger } from 'src/core/server';
99
import { loggingServiceMock } from 'src/core/server/mocks';
@@ -19,6 +19,8 @@ import { CURRENT_MAJOR_VERSION, PREV_MAJOR_VERSION } from '../../../common/versi
1919
import { licensingMock } from '../../../../licensing/server/mocks';
2020
import { LicensingPluginSetup } from '../../../../licensing/server';
2121

22+
import { esIndicesStateCheck } from '../es_indices_state_check';
23+
2224
import {
2325
isMlIndex,
2426
isWatcherIndex,
@@ -43,6 +45,7 @@ describe('reindexService', () => {
4345
Promise.reject(`Mock function ${name} was not implemented!`);
4446

4547
beforeEach(() => {
48+
(esIndicesStateCheck as jest.Mock).mockResolvedValue({});
4649
actions = {
4750
createReindexOp: jest.fn(unimplemented('createReindexOp')),
4851
deleteReindexOp: jest.fn(unimplemented('deleteReindexOp')),
@@ -844,7 +847,6 @@ describe('reindexService', () => {
844847
attributes: {
845848
...defaultAttributes,
846849
lastCompletedStep: ReindexStep.newIndexCreated,
847-
reindexOptions: { openAndClose: false },
848850
},
849851
} as ReindexSavedObject;
850852

x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import { APICaller, Logger } from 'src/core/server';
77
import { first } from 'rxjs/operators';
88

9+
import { LicensingPluginSetup } from '../../../../licensing/server';
10+
911
import {
1012
IndexGroup,
1113
ReindexOptions,
@@ -15,14 +17,16 @@ import {
1517
ReindexWarning,
1618
} from '../../../common/types';
1719

20+
import { esIndicesStateCheck } from '../es_indices_state_check';
21+
1822
import {
1923
generateNewIndexName,
2024
getReindexWarnings,
2125
sourceNameForIndex,
2226
transformFlatSettings,
2327
} from './index_settings';
28+
2429
import { ReindexActions } from './reindex_actions';
25-
import { LicensingPluginSetup } from '../../../../licensing/server';
2630

2731
import { error } from './error';
2832

@@ -317,7 +321,12 @@ export const reindexServiceFactory = (
317321
const startReindexing = async (reindexOp: ReindexSavedObject) => {
318322
const { indexName, reindexOptions } = reindexOp.attributes;
319323

320-
if (reindexOptions?.openAndClose === true) {
324+
// Where possible, derive reindex options at the last moment before reindexing
325+
// to prevent them from becoming stale as they wait in the queue.
326+
const indicesState = await esIndicesStateCheck(callAsUser, [indexName]);
327+
const openAndClose = indicesState[indexName] === 'close';
328+
if (indicesState[indexName] === 'close') {
329+
log.debug(`Detected closed index ${indexName}, opening...`);
321330
await callAsUser('indices.open', { index: indexName });
322331
}
323332

@@ -334,6 +343,12 @@ export const reindexServiceFactory = (
334343
lastCompletedStep: ReindexStep.reindexStarted,
335344
reindexTaskId: startReindex.task,
336345
reindexTaskPercComplete: 0,
346+
reindexOptions: {
347+
...(reindexOptions ?? {}),
348+
// Indicate to downstream states whether we opened a closed index that should be
349+
// closed again.
350+
openAndClose,
351+
},
337352
});
338353
};
339354

@@ -654,9 +669,16 @@ export const reindexServiceFactory = (
654669
throw new Error(`Reindex operation must be paused in order to be resumed.`);
655670
}
656671

672+
const reindexOptions: ReindexOptions | undefined = opts
673+
? {
674+
...(op.attributes.reindexOptions ?? {}),
675+
...opts,
676+
}
677+
: undefined;
678+
657679
return actions.updateReindexOp(op, {
658680
status: ReindexStatus.inProgress,
659-
reindexOptions: opts ?? op.attributes.reindexOptions,
681+
reindexOptions,
660682
});
661683
});
662684
},

x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_handler.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ interface ReindexHandlerArgs {
2424
headers: Record<string, any>;
2525
credentialStore: CredentialStore;
2626
reindexOptions?: {
27-
openAndClose?: boolean;
2827
enqueue?: boolean;
2928
};
3029
}
@@ -56,7 +55,6 @@ export const reindexHandler = async ({
5655

5756
const opts: ReindexOptions | undefined = reindexOptions
5857
? {
59-
openAndClose: reindexOptions.openAndClose,
6058
queueSettings: reindexOptions.enqueue ? { queuedAt: Date.now() } : undefined,
6159
}
6260
: undefined;

x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ const mockReindexService = {
2020
resumeReindexOperation: jest.fn(),
2121
cancelReindexing: jest.fn(),
2222
};
23-
jest.mock('../../lib/es_indices_state_check', () => ({ esIndicesStateCheck: jest.fn() }));
2423
jest.mock('../../lib/es_version_precheck', () => ({
2524
versionCheckHandlerWrapper: (a: any) => a,
2625
}));
@@ -39,7 +38,6 @@ import {
3938
} from '../../../common/types';
4039
import { credentialStoreFactory } from '../../lib/reindexing/credential_store';
4140
import { registerReindexIndicesRoutes } from './reindex_indices';
42-
import { esIndicesStateCheck } from '../../lib/es_indices_state_check';
4341

4442
/**
4543
* Since these route callbacks are so thin, these serve simply as integration tests
@@ -57,7 +55,6 @@ describe('reindex API', () => {
5755
} as any;
5856

5957
beforeEach(() => {
60-
(esIndicesStateCheck as jest.Mock).mockResolvedValue({});
6158
mockRouter = createMockRouter();
6259
routeDependencies = {
6360
credentialStore,
@@ -168,9 +165,7 @@ describe('reindex API', () => {
168165
);
169166

170167
// It called create correctly
171-
expect(mockReindexService.createReindexOperation).toHaveBeenCalledWith('theIndex', {
172-
openAndClose: false,
173-
});
168+
expect(mockReindexService.createReindexOperation).toHaveBeenCalledWith('theIndex', undefined);
174169

175170
// It returned the right results
176171
expect(resp.status).toEqual(200);
@@ -237,10 +232,7 @@ describe('reindex API', () => {
237232
kibanaResponseFactory
238233
);
239234
// It called resume correctly
240-
expect(mockReindexService.resumeReindexOperation).toHaveBeenCalledWith('theIndex', {
241-
openAndClose: false,
242-
queueSettings: undefined,
243-
});
235+
expect(mockReindexService.resumeReindexOperation).toHaveBeenCalledWith('theIndex', undefined);
244236
expect(mockReindexService.createReindexOperation).not.toHaveBeenCalled();
245237

246238
// It returned the right results
@@ -269,7 +261,6 @@ describe('reindex API', () => {
269261

270262
describe('POST /api/upgrade_assistant/reindex/batch', () => {
271263
const queueSettingsArg = {
272-
openAndClose: false,
273264
queueSettings: { queuedAt: expect.any(Number) },
274265
};
275266
it('creates a collection of index operations', async () => {

x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import { LicensingPluginSetup } from '../../../../licensing/server';
1616
import { ReindexStatus } from '../../../common/types';
1717

1818
import { versionCheckHandlerWrapper } from '../../lib/es_version_precheck';
19-
import { esIndicesStateCheck } from '../../lib/es_indices_state_check';
2019
import { reindexServiceFactory, ReindexWorker } from '../../lib/reindexing';
2120
import { CredentialStore } from '../../lib/reindexing/credential_store';
2221
import { reindexActionsFactory } from '../../lib/reindexing/reindex_actions';
@@ -108,7 +107,6 @@ export function registerReindexIndicesRoutes(
108107
response
109108
) => {
110109
const { indexName } = request.params;
111-
const indexStates = await esIndicesStateCheck(dataClient, [indexName]);
112110
try {
113111
const result = await reindexHandler({
114112
savedObjects: savedObjectsClient,
@@ -118,7 +116,6 @@ export function registerReindexIndicesRoutes(
118116
licensing,
119117
headers: request.headers,
120118
credentialStore,
121-
reindexOptions: { openAndClose: indexStates[indexName] === 'close' },
122119
});
123120

124121
// Kick the worker on this node to immediately pickup the new reindex operation.
@@ -190,7 +187,6 @@ export function registerReindexIndicesRoutes(
190187
response
191188
) => {
192189
const { indexNames } = request.body;
193-
const indexStates = await esIndicesStateCheck(dataClient, indexNames);
194190
const results: PostBatchResponse = {
195191
enqueued: [],
196192
errors: [],
@@ -206,7 +202,6 @@ export function registerReindexIndicesRoutes(
206202
headers: request.headers,
207203
credentialStore,
208204
reindexOptions: {
209-
openAndClose: indexStates[indexName] === 'close',
210205
enqueue: true,
211206
},
212207
});

0 commit comments

Comments
 (0)