"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.useTotalHits = void 0; var _common = require("@kbn/data-plugin/common"); var _public = require("@kbn/data-plugin/public"); var _public2 = require("@kbn/data-views-plugin/public"); var _common2 = require("@kbn/expressions-plugin/common"); var _i18n = require("@kbn/i18n"); var _react = require("react"); var _useEffectOnce = _interopRequireDefault(require("react-use/lib/useEffectOnce")); var _rxjs = require("rxjs"); var _types = require("../../types"); var _use_stable_callback = require("./use_stable_callback"); /* * 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 useTotalHits = ({ services, dataView, request, hits, chartVisible, filters, query, getTimeRange, refetch$, onTotalHitsChange, isPlainRecord }) => { const abortController = (0, _react.useRef)(); const fetch = (0, _use_stable_callback.useStableCallback)(() => { fetchTotalHits({ services, abortController, dataView, request, hits, chartVisible, filters, query, timeRange: getTimeRange(), onTotalHitsChange, isPlainRecord }); }); (0, _useEffectOnce.default)(fetch); (0, _react.useEffect)(() => { const subscription = refetch$.subscribe(fetch); return () => subscription.unsubscribe(); }, [fetch, refetch$]); }; exports.useTotalHits = useTotalHits; const fetchTotalHits = async ({ services, abortController, dataView, request, hits, chartVisible, filters, query, timeRange, onTotalHitsChange, isPlainRecord }) => { var _abortController$curr; (_abortController$curr = abortController.current) === null || _abortController$curr === void 0 ? void 0 : _abortController$curr.abort(); abortController.current = undefined; // Either the chart is visible, in which case Lens will make the request, // or there is no hits context, which means the total hits should be hidden if (chartVisible || !hits) { return; } onTotalHitsChange === null || onTotalHitsChange === void 0 ? void 0 : onTotalHitsChange(_types.UnifiedHistogramFetchStatus.loading, hits.total); const newAbortController = new AbortController(); abortController.current = newAbortController; const response = isPlainRecord ? await fetchTotalHitsTextBased({ services, abortController: newAbortController, dataView, request, query, timeRange }) : await fetchTotalHitsSearchSource({ services, abortController: newAbortController, dataView, request, filters, query, timeRange }); if (!response) { return; } onTotalHitsChange === null || onTotalHitsChange === void 0 ? void 0 : onTotalHitsChange(response.resultStatus, response.result); }; const fetchTotalHitsSearchSource = async ({ services: { data }, abortController, dataView, request, filters: originalFilters, query, timeRange }) => { const searchSource = data.search.searchSource.createEmpty(); searchSource.setField('index', dataView).setField('query', query).setField('size', 0).setField('trackTotalHits', true); let filters = originalFilters; if (dataView.type === _public2.DataViewType.ROLLUP) { // We treat that data view as "normal" even if it was a rollup data view, // since the rollup endpoint does not support querying individual documents, but we // can get them from the regular _search API that will be used if the data view // not a rollup data view. searchSource.setOverwriteDataViewType(undefined); } else { // Set the date range filter fields from timeFilter using the absolute format. // Search sessions requires that it be converted from a relative range const timeFilter = data.query.timefilter.timefilter.createFilter(dataView, timeRange); if (timeFilter) { filters = [...filters, timeFilter]; } } searchSource.setField('filter', filters); // Let the consumer inspect the request if they want to track it const inspector = request !== null && request !== void 0 && request.adapter ? { adapter: request.adapter, title: _i18n.i18n.translate('unifiedHistogram.inspectorRequestDataTitleTotalHits', { defaultMessage: 'Total hits' }), description: _i18n.i18n.translate('unifiedHistogram.inspectorRequestDescriptionTotalHits', { defaultMessage: 'This request queries Elasticsearch to fetch the total hits.' }) } : undefined; const fetch$ = searchSource.fetch$({ inspector, sessionId: request === null || request === void 0 ? void 0 : request.searchSessionId, abortSignal: abortController.signal, executionContext: { description: 'fetch total hits' }, disableShardFailureWarning: true // TODO: show warnings as a badge next to total hits number }).pipe((0, _rxjs.filter)(res => (0, _public.isCompleteResponse)(res)), (0, _rxjs.map)(res => res.rawResponse.hits.total), (0, _rxjs.catchError)(error => (0, _rxjs.of)(error))); const result = await (0, _rxjs.lastValueFrom)(fetch$); const resultStatus = result instanceof Error ? _types.UnifiedHistogramFetchStatus.error : _types.UnifiedHistogramFetchStatus.complete; return { resultStatus, result }; }; const fetchTotalHitsTextBased = async ({ services: { expressions }, abortController, dataView, request, query, timeRange }) => { const ast = await (0, _common.textBasedQueryStateToAstWithValidation)({ query, time: timeRange, dataView }); if (abortController.signal.aborted) { return undefined; } if (!ast) { return { resultStatus: _types.UnifiedHistogramFetchStatus.error, result: new Error('Invalid text based query') }; } const result = await (0, _rxjs.lastValueFrom)(expressions.run(ast, null, { inspectorAdapters: { requests: request === null || request === void 0 ? void 0 : request.adapter }, searchSessionId: request === null || request === void 0 ? void 0 : request.searchSessionId, executionContext: { description: 'fetch total hits' } }).pipe((0, _rxjs.pluck)('result'))); if (abortController.signal.aborted) { return undefined; } if ((0, _common2.isExpressionValueError)(result)) { return { resultStatus: _types.UnifiedHistogramFetchStatus.error, result: new Error(result.error.message) }; } return { resultStatus: _types.UnifiedHistogramFetchStatus.complete, result: result.rows.length }; };