From c77c8ab2abe0364dc0a286ea44cb4b203d5721eb Mon Sep 17 00:00:00 2001
From: Yulia Cech
Date: Thu, 7 Oct 2021 13:49:03 +0200
Subject: [PATCH] [Upgrade Assistant] Added reindexing progress in % to the
reindex flyout and es deprecations table
---
.../reindex_deprecation_flyout.test.ts | 107 +++++++++++++++
.../checklist_step.test.tsx.snap | 11 --
.../reindex/flyout/checklist_step.tsx | 9 --
.../reindex/flyout/progress.test.tsx | 125 +++++++++---------
.../reindex/flyout/progress.tsx | 98 ++++++++------
.../reindex/resolution_table_cell.tsx | 9 +-
.../reindex/use_reindex_state.tsx | 4 +-
.../public/application/lib/utils.test.ts | 33 ++++-
.../public/application/lib/utils.ts | 50 +++++++
9 files changed, 323 insertions(+), 123 deletions(-)
diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts
index ca9253c1140b0..3c6fe0e5f5329 100644
--- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts
+++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts
@@ -10,6 +10,7 @@ import { act } from 'react-dom/test-utils';
import { setupEnvironment } from '../helpers';
import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers';
import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, MOCK_JOB_ID } from './mocked_responses';
+import { ReindexStatus, ReindexStep } from '../../../common/types';
// Note: The reindexing flyout UX is subject to change; more tests should be added here once functionality is built out
describe('Reindex deprecation flyout', () => {
@@ -93,4 +94,110 @@ describe('Reindex deprecation flyout', () => {
expect(exists('reindexDetails.fetchFailedCallout')).toBe(true);
});
+
+ describe('reindexing progress', () => {
+ it('has not started yet', async () => {
+ const { actions, find, exists } = testBed;
+
+ await actions.table.clickDeprecationRowAt('reindex', 0);
+ expect(find('reindexChecklistTitle').text()).toEqual('Reindexing process');
+ expect(exists('cancelReindexingDocumentsButton')).toBe(false);
+ });
+
+ it('has started but not yet reindexing documents', async () => {
+ httpRequestsMockHelpers.setReindexStatusResponse({
+ reindexOp: {
+ status: ReindexStatus.inProgress,
+ lastCompletedStep: ReindexStep.readonly,
+ reindexTaskPercComplete: null,
+ },
+ warnings: [],
+ hasRequiredPrivileges: true,
+ });
+
+ await act(async () => {
+ testBed = await setupElasticsearchPage({ isReadOnlyMode: false });
+ });
+
+ testBed.component.update();
+ const { actions, find, exists } = testBed;
+
+ await actions.table.clickDeprecationRowAt('reindex', 0);
+
+ expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 5%');
+ expect(exists('cancelReindexingDocumentsButton')).toBe(false);
+ });
+
+ it('has started reindexing documents', async () => {
+ httpRequestsMockHelpers.setReindexStatusResponse({
+ reindexOp: {
+ status: ReindexStatus.inProgress,
+ lastCompletedStep: ReindexStep.reindexStarted,
+ reindexTaskPercComplete: 0.25,
+ },
+ warnings: [],
+ hasRequiredPrivileges: true,
+ });
+
+ await act(async () => {
+ testBed = await setupElasticsearchPage({ isReadOnlyMode: false });
+ });
+
+ testBed.component.update();
+ const { actions, find, exists } = testBed;
+
+ await actions.table.clickDeprecationRowAt('reindex', 0);
+
+ expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 31%');
+ expect(exists('cancelReindexingDocumentsButton')).toBe(true);
+ });
+
+ it('has completed reindexing documents', async () => {
+ httpRequestsMockHelpers.setReindexStatusResponse({
+ reindexOp: {
+ status: ReindexStatus.inProgress,
+ lastCompletedStep: ReindexStep.reindexCompleted,
+ reindexTaskPercComplete: 1,
+ },
+ warnings: [],
+ hasRequiredPrivileges: true,
+ });
+
+ await act(async () => {
+ testBed = await setupElasticsearchPage({ isReadOnlyMode: false });
+ });
+
+ testBed.component.update();
+ const { actions, find, exists } = testBed;
+
+ await actions.table.clickDeprecationRowAt('reindex', 0);
+
+ expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 95%');
+ expect(exists('cancelReindexingDocumentsButton')).toBe(false);
+ });
+
+ it('has completed', async () => {
+ httpRequestsMockHelpers.setReindexStatusResponse({
+ reindexOp: {
+ status: ReindexStatus.completed,
+ lastCompletedStep: ReindexStep.aliasCreated,
+ reindexTaskPercComplete: 1,
+ },
+ warnings: [],
+ hasRequiredPrivileges: true,
+ });
+
+ await act(async () => {
+ testBed = await setupElasticsearchPage({ isReadOnlyMode: false });
+ });
+
+ testBed.component.update();
+ const { actions, find, exists } = testBed;
+
+ await actions.table.clickDeprecationRowAt('reindex', 0);
+
+ expect(find('reindexChecklistTitle').text()).toEqual('Reindexing process');
+ expect(exists('cancelReindexingDocumentsButton')).toBe(false);
+ });
+ });
});
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap
index 26119c2b62040..be84bbf143ab3 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/__snapshots__/checklist_step.test.tsx.snap
@@ -30,17 +30,6 @@ exports[`ChecklistFlyout renders 1`] = `
-
-
-
-
-
-
-
-
-
-
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx
index c58230b3563f3..ad1c7d8e94105 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx
@@ -29,45 +29,69 @@ describe('ReindexProgress', () => {
);
expect(wrapper).toMatchInlineSnapshot(`
-,
- },
- Object {
- "status": "incomplete",
- "title": ,
- },
- Object {
- "status": "incomplete",
- "title": ,
- },
- Object {
- "status": "incomplete",
- "title": ,
- },
- ]
- }
-/>
-`);
+
+
+
+
+
+
+ ,
+ },
+ Object {
+ "status": "incomplete",
+ "title": ,
+ },
+ Object {
+ "status": "incomplete",
+ "title":
+
+
+
+ ,
+ },
+ Object {
+ "status": "incomplete",
+ "title": ,
+ },
+ ]
+ }
+ />
+
+ `);
});
it('displays errors in the step that failed', () => {
@@ -84,30 +108,9 @@ describe('ReindexProgress', () => {
cancelReindex={jest.fn()}
/>
);
-
- const aliasStep = wrapper.props().steps[3];
+ const aliasStep = (wrapper.find('StepProgress').props() as any).steps[3];
expect(aliasStep.children.props.errorMessage).toEqual(
`This is an error that happened on alias switch`
);
});
-
- it('shows reindexing document progress bar', () => {
- const wrapper = shallow(
-
- );
-
- const reindexStep = wrapper.props().steps[2];
- expect(reindexStep.children.type.name).toEqual('ReindexProgressBar');
- expect(reindexStep.children.props.reindexState.reindexTaskPercComplete).toEqual(0.25);
- });
});
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx
index 7a2c9943691a3..afeac303284f1 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx
@@ -12,8 +12,8 @@ import {
EuiCallOut,
EuiFlexGroup,
EuiFlexItem,
- EuiProgress,
EuiText,
+ EuiTitle,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -21,6 +21,7 @@ import { ReindexStatus, ReindexStep } from '../../../../../../../common/types';
import { LoadingState } from '../../../../types';
import type { ReindexState } from '../use_reindex_state';
import { StepProgress, StepProgressStep } from './step_progress';
+import { getReindexProgressLabel } from '../../../../../lib/utils';
const ErrorCallout: React.FunctionComponent<{ errorMessage: string | null }> = ({
errorMessage,
@@ -39,19 +40,10 @@ const PausedCallout = () => (
/>
);
-const ReindexProgressBar: React.FunctionComponent<{
+const CancelReindexingDocumentsButton: React.FunctionComponent<{
reindexState: ReindexState;
cancelReindex: () => void;
-}> = ({
- reindexState: { lastCompletedStep, status, reindexTaskPercComplete, cancelLoadingState },
- cancelReindex,
-}) => {
- const progressBar = reindexTaskPercComplete ? (
-
- ) : (
-
- );
-
+}> = ({ reindexState: { lastCompletedStep, status, cancelLoadingState }, cancelReindex }) => {
let cancelText: React.ReactNode;
switch (cancelLoadingState) {
case LoadingState.Loading:
@@ -71,7 +63,6 @@ const ReindexProgressBar: React.FunctionComponent<{
);
break;
case LoadingState.Error:
- cancelText = 'Could not cancel';
cancelText = (
- {progressBar}
-
-
- {cancelText}
-
-
-
+
+ {cancelText}
+
);
};
@@ -118,7 +105,12 @@ export const ReindexProgress: React.FunctionComponent<{
reindexState: ReindexState;
cancelReindex: () => void;
}> = (props) => {
- const { errorMessage, lastCompletedStep = -1, status } = props.reindexState;
+ const {
+ errorMessage,
+ lastCompletedStep = -1,
+ status,
+ reindexTaskPercComplete,
+ } = props.reindexState;
const stepDetails = (thisStep: ReindexStep): Pick => {
const previousStep = orderedSteps[orderedSteps.indexOf(thisStep) - 1];
@@ -151,14 +143,23 @@ export const ReindexProgress: React.FunctionComponent<{
}
};
- // The reindexing step is special because it combines the starting and complete statuses into a single UI
- // with a progress bar.
+ // The reindexing step is special because it generally lasts longer and can be cancelled mid-flight
const reindexingDocsStep = {
title: (
-
+
+
+
+
+ {(lastCompletedStep === ReindexStep.newIndexCreated ||
+ lastCompletedStep === ReindexStep.reindexStarted) && (
+
+
+
+ )}
+
),
} as StepProgressStep;
@@ -189,7 +190,6 @@ export const ReindexProgress: React.FunctionComponent<{
lastCompletedStep === ReindexStep.reindexStarted
) {
reindexingDocsStep.status = 'inProgress';
- reindexingDocsStep.children = ;
} else {
reindexingDocsStep.status = 'complete';
}
@@ -225,5 +225,27 @@ export const ReindexProgress: React.FunctionComponent<{
},
];
- return ;
+ return (
+ <>
+
+
+ {status === ReindexStatus.inProgress ? (
+
+ ) : (
+
+ )}
+
+
+
+ >
+ );
};
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx
index ff2f01befb180..84c6c16d4032a 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx
@@ -17,6 +17,7 @@ import {
EuiToolTip,
} from '@elastic/eui';
import { ReindexStatus } from '../../../../../../common/types';
+import { getReindexProgressLabel } from '../../../../lib/utils';
import { LoadingState } from '../../../types';
import { useReindexContext } from './context';
@@ -99,7 +100,13 @@ export const ReindexResolutionCell: React.FunctionComponent = () => {
- {i18nTexts.reindexInProgressText}
+
+ {i18nTexts.reindexInProgressText}{' '}
+ {getReindexProgressLabel(
+ reindexState.reindexTaskPercComplete,
+ reindexState.lastCompletedStep
+ )}
+
);
diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx
index 32a6c75ff6eec..cbeebd00f2bb8 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx
+++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx
@@ -127,7 +127,7 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A
api.sendReindexTelemetryData({ start: true });
- const { data, error } = await api.startReindexTask(indexName);
+ const { data: reindexOp, error } = await api.startReindexTask(indexName);
if (error) {
setReindexState({
@@ -139,7 +139,7 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A
return;
}
- setReindexState(getReindexState(reindexState, data));
+ setReindexState(getReindexState(reindexState, { reindexOp }));
updateStatus();
}, [api, indexName, reindexState, updateStatus]);
diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts
index 83fc9cabbbecc..37392c832ecf5 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts
+++ b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts
@@ -6,7 +6,8 @@
*/
import { DEPRECATION_WARNING_UPPER_LIMIT } from '../../../common/constants';
-import { validateRegExpString, getDeprecationsUpperLimit } from './utils';
+import { getDeprecationsUpperLimit, getReindexProgressLabel, validateRegExpString } from './utils';
+import { ReindexStep } from '../../../common/types';
describe('validRegExpString', () => {
it('correctly returns false for invalid strings', () => {
@@ -35,3 +36,33 @@ describe('getDeprecationsUpperLimit', () => {
);
});
});
+
+describe('getReindexProgressLabel', () => {
+ it('returns 0% when the reindex task has just been created', () => {
+ expect(getReindexProgressLabel(null, ReindexStep.created)).toBe('0%');
+ });
+
+ it('returns 5% when the index has been made read-only', () => {
+ expect(getReindexProgressLabel(null, ReindexStep.readonly)).toBe('5%');
+ });
+
+ it('returns 10% when the reindexing documents has started, but the progress is null', () => {
+ expect(getReindexProgressLabel(null, ReindexStep.reindexStarted)).toBe('10%');
+ });
+
+ it('returns 10% when the reindexing documents has started, but the progress is 0', () => {
+ expect(getReindexProgressLabel(0, ReindexStep.reindexStarted)).toBe('10%');
+ });
+
+ it('returns 53% when the reindexing documents progress is 0.5', () => {
+ expect(getReindexProgressLabel(0.5, ReindexStep.reindexStarted)).toBe('53%');
+ });
+
+ it('returns 95% when the reindexing documents progress is 1', () => {
+ expect(getReindexProgressLabel(1, ReindexStep.reindexStarted)).toBe('95%');
+ });
+
+ it('returns 100% when alias has been switched', () => {
+ expect(getReindexProgressLabel(null, ReindexStep.aliasCreated)).toBe('100%');
+ });
+});
diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts
index b90038e1166ab..f7849d8ec6ece 100644
--- a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts
+++ b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts
@@ -9,6 +9,7 @@ import { pipe } from 'fp-ts/lib/pipeable';
import { tryCatch, fold } from 'fp-ts/lib/Either';
import { DEPRECATION_WARNING_UPPER_LIMIT } from '../../../common/constants';
+import { ReindexStep } from '../../../common/types';
export const validateRegExpString = (s: string) =>
pipe(
@@ -34,3 +35,52 @@ export const getDeprecationsUpperLimit = (count: number) => {
return count.toString();
};
+
+/*
+ * Reindexing task consists of 4 steps: making the index read-only, creating a new index,
+ * reindexing documents into the new index and switching alias from the old to the new index.
+ * Steps 1, 2 and 4 each contribute 5% to the overall progress.
+ * Step 3 (reindexing documents) can take a long time for large indices and its progress is calculated
+ * between 10% and 95% of the overall progress depending on its completeness percentage.
+ */
+export const getReindexProgressLabel = (
+ reindexingDocumentsProgress: number | null,
+ lastCompletedStep: ReindexStep | undefined
+): string => {
+ let percentsComplete = 0;
+ switch (lastCompletedStep) {
+ case ReindexStep.created:
+ // the reindex task has just started, 0% progress
+ percentsComplete = 0;
+ break;
+ case ReindexStep.readonly: {
+ // step 1 completed, 5% progress
+ percentsComplete = 5;
+ break;
+ }
+ case ReindexStep.newIndexCreated: {
+ // step 2 completed, 10% progress
+ percentsComplete = 10;
+ break;
+ }
+ case ReindexStep.reindexStarted: {
+ // step 3 started, 10-95% progress depending on progress of reindexing documents in ES
+ percentsComplete =
+ reindexingDocumentsProgress !== null
+ ? 10 + Math.round(reindexingDocumentsProgress * 85)
+ : 10;
+ break;
+ }
+ case ReindexStep.reindexCompleted: {
+ // step 3 completed, only step 4 remaining, 95% progress
+ percentsComplete = 95;
+ break;
+ }
+ case ReindexStep.aliasCreated: {
+ // step 4 completed, 100% progress
+ percentsComplete = 100;
+ break;
+ }
+ }
+ return `${percentsComplete}%`;
+};