From d8a2f8f95c05a9b94d1969487433539954fd12ef Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Mon, 17 May 2021 11:46:57 +0200 Subject: [PATCH] Improve migration perf (#99773) * Do not clone state, use TypeCheck it's not mutated * do not recreate context for every migration * use more optional semver check * update SavedObjectMigrationContext type * add a test model returns new state object * update docs Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- ...text.converttomultinamespacetypeversion.md | 2 +- ...-server.savedobjectmigrationcontext.log.md | 2 +- ...objectmigrationcontext.migrationversion.md | 2 +- .../migrations/core/document_migrator.ts | 11 ++++---- .../server/saved_objects/migrations/types.ts | 6 ++--- .../saved_objects/migrationsv2/model.test.ts | 25 +++++++++++++++++++ .../saved_objects/migrationsv2/model.ts | 4 +-- .../saved_objects/migrationsv2/types.ts | 5 ++-- src/core/server/server.api.md | 6 ++--- .../common/saved_dashboard_references.ts | 5 ++-- 10 files changed, 47 insertions(+), 21 deletions(-) diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.converttomultinamespacetypeversion.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.converttomultinamespacetypeversion.md index 2a30693f4da8..9fe43a2f3f47 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.converttomultinamespacetypeversion.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.converttomultinamespacetypeversion.md @@ -9,5 +9,5 @@ The version in which this object type is being converted to a multi-namespace ty Signature: ```typescript -convertToMultiNamespaceTypeVersion?: string; +readonly convertToMultiNamespaceTypeVersion?: string; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.log.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.log.md index a1b3378afc53..20a0e99275a3 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.log.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.log.md @@ -9,5 +9,5 @@ logger instance to be used by the migration handler Signature: ```typescript -log: SavedObjectsMigrationLogger; +readonly log: SavedObjectsMigrationLogger; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.migrationversion.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.migrationversion.md index 7b20ae41048f..a1c2717e6e4a 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.migrationversion.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectmigrationcontext.migrationversion.md @@ -9,5 +9,5 @@ The migration version that this migration function is defined for Signature: ```typescript -migrationVersion: string; +readonly migrationVersion: string; ``` diff --git a/src/core/server/saved_objects/migrations/core/document_migrator.ts b/src/core/server/saved_objects/migrations/core/document_migrator.ts index f30cfc53018d..c96de6ebbfcd 100644 --- a/src/core/server/saved_objects/migrations/core/document_migrator.ts +++ b/src/core/server/saved_objects/migrations/core/document_migrator.ts @@ -661,13 +661,14 @@ function wrapWithTry( migrationFn: SavedObjectMigrationFn, log: Logger ) { + const context = Object.freeze({ + log: new MigrationLogger(log), + migrationVersion: version, + convertToMultiNamespaceTypeVersion: type.convertToMultiNamespaceTypeVersion, + }); + return function tryTransformDoc(doc: SavedObjectUnsanitizedDoc) { try { - const context = { - log: new MigrationLogger(log), - migrationVersion: version, - convertToMultiNamespaceTypeVersion: type.convertToMultiNamespaceTypeVersion, - }; const result = migrationFn(doc, context); // A basic sanity check to help migration authors detect basic errors diff --git a/src/core/server/saved_objects/migrations/types.ts b/src/core/server/saved_objects/migrations/types.ts index 619a7f85a327..570315e780eb 100644 --- a/src/core/server/saved_objects/migrations/types.ts +++ b/src/core/server/saved_objects/migrations/types.ts @@ -56,15 +56,15 @@ export interface SavedObjectMigrationContext { /** * logger instance to be used by the migration handler */ - log: SavedObjectsMigrationLogger; + readonly log: SavedObjectsMigrationLogger; /** * The migration version that this migration function is defined for */ - migrationVersion: string; + readonly migrationVersion: string; /** * The version in which this object type is being converted to a multi-namespace type */ - convertToMultiNamespaceTypeVersion?: string; + readonly convertToMultiNamespaceTypeVersion?: string; } /** diff --git a/src/core/server/saved_objects/migrationsv2/model.test.ts b/src/core/server/saved_objects/migrationsv2/model.test.ts index adeb78e568af..7a47e58f1947 100644 --- a/src/core/server/saved_objects/migrationsv2/model.test.ts +++ b/src/core/server/saved_objects/migrationsv2/model.test.ts @@ -198,6 +198,31 @@ describe('migrations v2 model', () => { }); describe('model transitions from', () => { + it('transition returns new state', () => { + const initState: State = { + ...baseState, + controlState: 'INIT', + currentAlias: '.kibana', + versionAlias: '.kibana_7.11.0', + versionIndex: '.kibana_7.11.0_001', + }; + + const res: ResponseType<'INIT'> = Either.right({ + '.kibana_7.11.0_001': { + aliases: { + '.kibana': {}, + '.kibana_7.11.0': {}, + }, + mappings: { + properties: {}, + }, + settings: {}, + }, + }); + const newState = model(initState, res); + expect(newState).not.toBe(initState); + }); + describe('INIT', () => { const initState: State = { ...baseState, diff --git a/src/core/server/saved_objects/migrationsv2/model.ts b/src/core/server/saved_objects/migrationsv2/model.ts index 3ef3cb4f83b6..f4185225ae07 100644 --- a/src/core/server/saved_objects/migrationsv2/model.ts +++ b/src/core/server/saved_objects/migrationsv2/model.ts @@ -9,7 +9,7 @@ import { gt, valid } from 'semver'; import * as Either from 'fp-ts/lib/Either'; import * as Option from 'fp-ts/lib/Option'; -import { cloneDeep } from 'lodash'; + import { AliasAction, FetchIndexResponse, isLeftTypeof, RetryableEsClientError } from './actions'; import { AllActionStates, InitState, State } from './types'; import { IndexMapping } from '../mappings'; @@ -187,7 +187,7 @@ export const model = (currentState: State, resW: ResponseType): // control state using: // `const res = resW as ResponseType;` - let stateP: State = cloneDeep(currentState); + let stateP: State = currentState; // Handle retryable_es_client_errors. Other left values need to be handled // by the control state specific code below. diff --git a/src/core/server/saved_objects/migrationsv2/types.ts b/src/core/server/saved_objects/migrationsv2/types.ts index e3e52212d56c..adcd2ad32fd2 100644 --- a/src/core/server/saved_objects/migrationsv2/types.ts +++ b/src/core/server/saved_objects/migrationsv2/types.ts @@ -381,7 +381,7 @@ export interface LegacyDeleteState extends LegacyBaseState { readonly controlState: 'LEGACY_DELETE'; } -export type State = +export type State = Readonly< | FatalState | InitState | DoneState @@ -411,7 +411,8 @@ export type State = | LegacySetWriteBlockState | LegacyReindexState | LegacyReindexWaitForTaskState - | LegacyDeleteState; + | LegacyDeleteState +>; export type AllControlStates = State['controlState']; /** diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 972e220baae3..3e6a69d15919 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2152,9 +2152,9 @@ export interface SavedObjectExportBaseOptions { // @public export interface SavedObjectMigrationContext { - convertToMultiNamespaceTypeVersion?: string; - log: SavedObjectsMigrationLogger; - migrationVersion: string; + readonly convertToMultiNamespaceTypeVersion?: string; + readonly log: SavedObjectsMigrationLogger; + readonly migrationVersion: string; } // @public diff --git a/src/plugins/dashboard/common/saved_dashboard_references.ts b/src/plugins/dashboard/common/saved_dashboard_references.ts index 16ab470ce7d6..9f0858759d0d 100644 --- a/src/plugins/dashboard/common/saved_dashboard_references.ts +++ b/src/plugins/dashboard/common/saved_dashboard_references.ts @@ -5,8 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - -import semverSatisfies from 'semver/functions/satisfies'; +import Semver from 'semver'; import { SavedObjectAttributes, SavedObjectReference } from '../../../core/types'; import { DashboardContainerStateWithType, DashboardPanelState } from './types'; import { EmbeddablePersistableStateService } from '../../embeddable/common/types'; @@ -24,7 +23,7 @@ export interface SavedObjectAttributesAndReferences { } const isPre730Panel = (panel: Record): boolean => { - return 'version' in panel ? semverSatisfies(panel.version, '<7.3') : true; + return 'version' in panel ? Semver.gt('7.3.0', panel.version) : true; }; function dashboardAttributesToState(