"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.runV2Migration = void 0;
var _semver = _interopRequireDefault(require("semver"));
var _core = require("./core");
var _kibana_migrator_utils = require("./kibana_migrator_utils");
var _run_resilient_migrator = require("./run_resilient_migrator");
var _migrate_raw_docs = require("./core/migrate_raw_docs");
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

const runV2Migration = async options => {
  const indexMap = (0, _core.createIndexMap)({
    kibanaIndexName: options.kibanaIndexPrefix,
    indexMap: options.mappingProperties,
    registry: options.typeRegistry
  });
  options.logger.debug('Applying registered migrations for the following saved object types:');
  Object.entries(options.documentMigrator.getMigrationVersion()).sort(([t1, v1], [t2, v2]) => {
    return _semver.default.compare(v1, v2);
  }).forEach(([type, migrationVersion]) => {
    options.logger.debug(`migrationVersion: ${migrationVersion} saved object type: ${type}`);
  });

  // build a indexTypesMap from the info present in the typeRegistry, e.g.:
  // {
  //   '.kibana': ['typeA', 'typeB', ...]
  //   '.kibana_task_manager': ['task', ...]
  //   '.kibana_cases': ['typeC', 'typeD', ...]
  //   ...
  // }
  const indexTypesMap = (0, _kibana_migrator_utils.indexMapToIndexTypesMap)(indexMap);

  // compare indexTypesMap with the one present (or not) in the .kibana index meta
  // and check if some SO types have been moved to different indices
  const indicesWithRelocatingTypes = await (0, _kibana_migrator_utils.getIndicesInvolvedInRelocation)({
    mainIndex: options.kibanaIndexPrefix,
    client: options.elasticsearchClient,
    indexTypesMap,
    logger: options.logger,
    defaultIndexTypesMap: options.defaultIndexTypesMap
  });

  // we create synchronization objects (synchronization points) for each of the
  // migrators involved in relocations, aka each of the migrators that will:
  // A) reindex some documents TO other indices
  // B) receive some documents FROM other indices
  // C) both
  const readyToReindexWaitGroupMap = (0, _kibana_migrator_utils.createWaitGroupMap)(indicesWithRelocatingTypes);
  const doneReindexingWaitGroupMap = (0, _kibana_migrator_utils.createWaitGroupMap)(indicesWithRelocatingTypes);
  const updateAliasesWaitGroupMap = (0, _kibana_migrator_utils.createWaitGroupMap)(indicesWithRelocatingTypes);

  // build a list of all migrators that must be started
  const migratorIndices = new Set(Object.keys(indexMap));
  // the types in indices involved in relocation might not have mappings in the current mappings anymore
  // but if their SOs must be relocated to another index, we still need a migrator to do the job
  indicesWithRelocatingTypes.forEach(index => migratorIndices.add(index));
  const migrators = Array.from(migratorIndices).map((indexName, i) => {
    return {
      migrate: () => {
        var _indexMap$indexName$t, _indexMap$indexName, _indexMap$indexName2;
        const readyToReindex = readyToReindexWaitGroupMap[indexName];
        const doneReindexing = doneReindexingWaitGroupMap[indexName];
        const updateRelocationAliases = updateAliasesWaitGroupMap[indexName];
        // check if this migrator's index is involved in some document redistribution
        const mustRelocateDocuments = indicesWithRelocatingTypes.includes(indexName);
        return (0, _run_resilient_migrator.runResilientMigrator)({
          client: options.elasticsearchClient,
          kibanaVersion: options.kibanaVersion,
          mustRelocateDocuments,
          indexTypesMap,
          waitForMigrationCompletion: options.waitForMigrationCompletion,
          // a migrator's index might no longer have any associated types to it
          targetMappings: (0, _core.buildActiveMappings)((_indexMap$indexName$t = (_indexMap$indexName = indexMap[indexName]) === null || _indexMap$indexName === void 0 ? void 0 : _indexMap$indexName.typeMappings) !== null && _indexMap$indexName$t !== void 0 ? _indexMap$indexName$t : {}),
          logger: options.logger,
          preMigrationScript: (_indexMap$indexName2 = indexMap[indexName]) === null || _indexMap$indexName2 === void 0 ? void 0 : _indexMap$indexName2.script,
          readyToReindex,
          doneReindexing,
          updateRelocationAliases,
          transformRawDocs: rawDocs => (0, _migrate_raw_docs.migrateRawDocsSafely)({
            serializer: options.serializer,
            migrateDoc: options.documentMigrator.migrateAndConvert,
            rawDocs
          }),
          coreMigrationVersionPerType: options.documentMigrator.getMigrationVersion({
            includeDeferred: false,
            migrationType: 'core'
          }),
          migrationVersionPerType: options.documentMigrator.getMigrationVersion({
            includeDeferred: false
          }),
          indexPrefix: indexName,
          migrationsConfig: options.migrationConfig,
          typeRegistry: options.typeRegistry,
          docLinks: options.docLinks,
          esCapabilities: options.esCapabilities
        });
      }
    };
  });
  return Promise.all(migrators.map(migrator => migrator.migrate()));
};
exports.runV2Migration = runV2Migration;