"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.cleanupUnknownAndExcluded = void 0;
var Either = _interopRequireWildcard(require("fp-ts/lib/Either"));
var TaskEither = _interopRequireWildcard(require("fp-ts/lib/TaskEither"));
var _function = require("fp-ts/lib/function");
var _check_for_unknown_docs = require("./check_for_unknown_docs");
var _ = require(".");
var _calculate_exclude_filters = require("./calculate_exclude_filters");
var _delete_by_query = require("./delete_by_query");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/*
 * 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.
 */

/** @internal */

/** @internal */

/**
 * Cleans up unknown and excluded types from the specified index.
 */
const cleanupUnknownAndExcluded = ({
  client,
  indexName,
  discardUnknownDocs,
  excludeOnUpgradeQuery,
  excludeFromUpgradeFilterHooks,
  hookTimeoutMs,
  knownTypes,
  removedTypes
}) => {
  let unknownDocs = [];
  let unknownDocTypes = [];
  let errorsByType = {};
  return (0, _function.pipe)(
  // check if there are unknown docs
  (0, _check_for_unknown_docs.checkForUnknownDocs)({
    client,
    indexName,
    knownTypes,
    excludeOnUpgradeQuery
  }),
  // make sure we are allowed to get rid of them (in case there are some)
  TaskEither.chainEitherKW(unknownDocsRes => {
    if ((0, _.isTypeof)(unknownDocsRes, 'unknown_docs_found')) {
      unknownDocs = unknownDocsRes.unknownDocs;
      unknownDocTypes = [...new Set(unknownDocs.map(({
        type
      }) => type))];
      if (!discardUnknownDocs) {
        return Either.left({
          type: 'unknown_docs_found',
          unknownDocs: unknownDocsRes.unknownDocs
        });
      }
    }
    return Either.right(undefined);
  }),
  // calculate exclude filters (we use them to build the query for documents that must be deleted)
  TaskEither.chainW(() => (0, _calculate_exclude_filters.calculateExcludeFilters)({
    client,
    excludeFromUpgradeFilterHooks,
    hookTimeoutMs
  })),
  // actively delete unwanted documents
  TaskEither.chainW(excludeFiltersRes => {
    errorsByType = excludeFiltersRes.errorsByType;

    // we must delete everything that matches:
    // - any of the plugin-defined exclude filters
    // - OR any of the unknown types
    const deleteQuery = {
      bool: {
        should: [...excludeFiltersRes.filterClauses, ...removedTypes.map(type => ({
          term: {
            type
          }
        })), ...unknownDocTypes.map(type => ({
          term: {
            type
          }
        }))]
      }
    };
    return (0, _delete_by_query.deleteByQuery)({
      client,
      indexName,
      query: deleteQuery,
      // we want to delete as many docs as we can in the current attempt
      conflicts: 'proceed',
      // instead of forcing refresh after each delete attempt,
      // we opt for a delayRetry mechanism when conflicts appear,
      // letting the periodic refresh kick in
      refresh: false
    });
  }),
  // map response output
  TaskEither.chainEitherKW(res => {
    return Either.right({
      type: 'cleanup_started',
      taskId: res.taskId,
      unknownDocs,
      errorsByType
    });
  }));
};
exports.cleanupUnknownAndExcluded = cleanupUnknownAndExcluded;