"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchAll = fetchAll; var _rxjs = require("rxjs"); var _ebtTools = require("@kbn/ebt-tools"); var _lodash = require("lodash"); var _update_search_source = require("./update_search_source"); var _get_raw_record_type = require("./get_raw_record_type"); var _use_saved_search_messages = require("../hooks/use_saved_search_messages"); var _fetch_documents = require("./fetch_documents"); var _types = require("../../types"); var _discover_data_state_container = require("../services/discover_data_state_container"); var _fetch_sql = require("./fetch_sql"); /* * 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. */ /** * This function starts fetching all required queries in Discover. This will be the query to load the individual * documents as well as any other requests that might be required to load the main view. * * This method returns a promise, which will resolve (without a value), as soon as all queries that have been started * have been completed (failed or successfully). */ function fetchAll(dataSubjects, reset = false, fetchDeps) { const { initialFetchStatus, getAppState, getInternalState, services, inspectorAdapters, savedSearch } = fetchDeps; const { data } = services; const searchSource = savedSearch.searchSource.createChild(); try { const dataView = searchSource.getField('index'); const query = getAppState().query; const prevQuery = dataSubjects.documents$.getValue().query; const recordRawType = (0, _get_raw_record_type.getRawRecordType)(query); if (reset) { (0, _use_saved_search_messages.sendResetMsg)(dataSubjects, initialFetchStatus, recordRawType); } const useSql = recordRawType === _discover_data_state_container.RecordRawType.PLAIN; if (recordRawType === _discover_data_state_container.RecordRawType.DOCUMENT) { // Update the base searchSource, base for all child fetches (0, _update_search_source.updateVolatileSearchSource)(searchSource, { dataView, services, sort: getAppState().sort, customFilters: getInternalState().customFilters }); } // Mark all subjects as loading (0, _use_saved_search_messages.sendLoadingMsg)(dataSubjects.main$, { recordRawType }); (0, _use_saved_search_messages.sendLoadingMsg)(dataSubjects.documents$, { recordRawType, query }); (0, _use_saved_search_messages.sendLoadingMsg)(dataSubjects.totalHits$, { recordRawType }); // Start fetching all required requests const response = useSql && query ? (0, _fetch_sql.fetchSql)(query, dataView, data, services.expressions, inspectorAdapters) : (0, _fetch_documents.fetchDocuments)(searchSource, fetchDeps); const fetchType = useSql && query ? 'fetchSql' : 'fetchDocuments'; const startTime = window.performance.now(); // Handle results of the individual queries and forward the results to the corresponding dataSubjects response.then(({ records, textBasedQueryColumns, interceptedWarnings }) => { if (services.analytics) { const duration = window.performance.now() - startTime; (0, _ebtTools.reportPerformanceMetricEvent)(services.analytics, { eventName: 'discoverFetchAllRequestsOnly', duration, meta: { fetchType } }); } // If the total hits (or chart) query is still loading, emit a partial // hit count that's at least our retrieved document count if (dataSubjects.totalHits$.getValue().fetchStatus === _types.FetchStatus.LOADING) { dataSubjects.totalHits$.next({ fetchStatus: _types.FetchStatus.PARTIAL, result: records.length, recordRawType }); } /** * The partial state for text based query languages is necessary in case the query has changed * In the follow up useTextBasedQueryLanguage hook in this case new columns are added to AppState * So the data table shows the new columns of the table. The partial state was introduced to prevent * To frequent change of state causing the table to re-render to often, which causes race conditions * So it takes too long, a bad user experience, also a potential flakniess in tests */ const fetchStatus = useSql && (!prevQuery || !(0, _lodash.isEqual)(query, prevQuery)) ? _types.FetchStatus.PARTIAL : _types.FetchStatus.COMPLETE; dataSubjects.documents$.next({ fetchStatus, result: records, textBasedQueryColumns, interceptedWarnings, recordRawType, query }); (0, _use_saved_search_messages.checkHitCount)(dataSubjects.main$, records.length); }) // Only the document query should send its errors to main$, to cause the full Discover app // to get into an error state. The other queries will not cause all of Discover to error out // but their errors will be shown in-place (e.g. of the chart). .catch((0, _use_saved_search_messages.sendErrorTo)(dataSubjects.documents$, dataSubjects.main$)); // Return a promise that will resolve once all the requests have finished or failed return (0, _rxjs.firstValueFrom)((0, _rxjs.merge)(fetchStatusByType(dataSubjects.documents$, 'documents'), fetchStatusByType(dataSubjects.totalHits$, 'totalHits')).pipe((0, _rxjs.scan)(toRequestFinishedMap, {}), (0, _rxjs.filter)(allRequestsFinished))).then(() => { // Send a complete message to main$ once all queries are done and if main$ // is not already in an ERROR state, e.g. because the document query has failed. // This will only complete main$, if it hasn't already been completed previously // by a query finding no results. if (dataSubjects.main$.getValue().fetchStatus !== _types.FetchStatus.ERROR) { (0, _use_saved_search_messages.sendCompleteMsg)(dataSubjects.main$); } }); } catch (error) { (0, _use_saved_search_messages.sendErrorMsg)(dataSubjects.main$, error); // We also want to return a resolved promise in an error case, since it just indicates we're done with querying. return Promise.resolve(); } } const fetchStatusByType = (subject, type) => subject.pipe((0, _rxjs.map)(({ fetchStatus }) => ({ type, fetchStatus }))); const toRequestFinishedMap = (currentMap, { type, fetchStatus }) => ({ ...currentMap, [type]: [_types.FetchStatus.COMPLETE, _types.FetchStatus.ERROR].includes(fetchStatus) }); const allRequestsFinished = requests => Object.values(requests).every(finished => finished);