"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.LogStreamProvider = void 0; exports.useLogStream = useLogStream; exports.useLogStreamContext = void 0; var _constate = _interopRequireDefault(require("constate")); var _lodash = require("lodash"); var _react = require("react"); var _usePrevious = _interopRequireDefault(require("react-use/lib/usePrevious")); var _useSetState = _interopRequireDefault(require("react-use/lib/useSetState")); var _use_observable = require("../../../utils/use_observable"); var _use_fetch_log_entries_after = require("./use_fetch_log_entries_after"); var _use_fetch_log_entries_around = require("./use_fetch_log_entries_around"); var _use_fetch_log_entries_before = require("./use_fetch_log_entries_before"); /* * 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; you may not use this file except in compliance with the Elastic License * 2.0. */ const INITIAL_STATE = { entries: [], topCursor: null, bottomCursor: null, // Assume there are pages available until the API proves us wrong hasMoreBefore: true, hasMoreAfter: true }; const LOG_ENTRIES_CHUNK_SIZE = 200; function useLogStream({ logViewReference, startTimestamp, endTimestamp, query, center, columns }) { const [state, setState] = (0, _useSetState.default)(INITIAL_STATE); const [resetOnSuccess, setResetOnSuccess] = (0, _react.useState)(false); // Ensure the pagination keeps working when the timerange gets extended const prevStartTimestamp = (0, _usePrevious.default)(startTimestamp); const prevEndTimestamp = (0, _usePrevious.default)(endTimestamp); const [cachedQuery, setCachedQuery] = (0, _react.useState)(query); if (!(0, _lodash.isEqual)(query, cachedQuery)) { setCachedQuery(query); } (0, _react.useEffect)(() => { if (prevStartTimestamp && prevStartTimestamp > startTimestamp) { setState({ hasMoreBefore: true }); } }, [prevStartTimestamp, startTimestamp, setState]); (0, _react.useEffect)(() => { if (prevEndTimestamp && prevEndTimestamp < endTimestamp) { setState({ hasMoreAfter: true }); } }, [prevEndTimestamp, endTimestamp, setState]); const commonFetchArguments = (0, _react.useMemo)(() => ({ logViewReference, startTimestamp, endTimestamp, query: cachedQuery, columnOverrides: columns }), [columns, endTimestamp, cachedQuery, logViewReference, startTimestamp]); const { fetchLogEntriesAround, isRequestRunning: isLogEntriesAroundRequestRunning, logEntriesAroundSearchResponses$ } = (0, _use_fetch_log_entries_around.useFetchLogEntriesAround)(commonFetchArguments); (0, _use_observable.useSubscription)(logEntriesAroundSearchResponses$, { next: ({ before, after, combined }) => { if ((before.response.data != null || (after === null || after === void 0 ? void 0 : after.response.data) != null) && !combined.isPartial) { setState(_prevState => { var _combined$hasMoreAfte, _combined$hasMoreBefo; const prevState = resetOnSuccess ? INITIAL_STATE : _prevState; return { ...(resetOnSuccess ? INITIAL_STATE : prevState), entries: combined.entries, hasMoreAfter: (_combined$hasMoreAfte = combined.hasMoreAfter) !== null && _combined$hasMoreAfte !== void 0 ? _combined$hasMoreAfte : prevState.hasMoreAfter, hasMoreBefore: (_combined$hasMoreBefo = combined.hasMoreBefore) !== null && _combined$hasMoreBefo !== void 0 ? _combined$hasMoreBefo : prevState.hasMoreBefore, bottomCursor: combined.bottomCursor, topCursor: combined.topCursor, lastLoadedTime: new Date() }; }); if (resetOnSuccess) { setResetOnSuccess(false); } } } }); const { fetchLogEntriesBefore, isRequestRunning: isLogEntriesBeforeRequestRunning, logEntriesBeforeSearchResponse$ } = (0, _use_fetch_log_entries_before.useFetchLogEntriesBefore)(commonFetchArguments); (0, _use_observable.useSubscription)(logEntriesBeforeSearchResponse$, { next: ({ response: { data, isPartial } }) => { if (data != null && !isPartial) { setState(_prevState => { var _data$hasMoreBefore, _data$topCursor, _prevState$bottomCurs; const prevState = resetOnSuccess ? INITIAL_STATE : _prevState; return { ...(resetOnSuccess ? INITIAL_STATE : prevState), entries: [...data.entries, ...prevState.entries], hasMoreBefore: (_data$hasMoreBefore = data.hasMoreBefore) !== null && _data$hasMoreBefore !== void 0 ? _data$hasMoreBefore : prevState.hasMoreBefore, topCursor: (_data$topCursor = data.topCursor) !== null && _data$topCursor !== void 0 ? _data$topCursor : prevState.topCursor, bottomCursor: (_prevState$bottomCurs = prevState.bottomCursor) !== null && _prevState$bottomCurs !== void 0 ? _prevState$bottomCurs : data.bottomCursor, lastLoadedTime: new Date() }; }); if (resetOnSuccess) { setResetOnSuccess(false); } } } }); const fetchPreviousEntries = (0, _react.useCallback)(params => { if (state.topCursor === null && state.hasMoreBefore) { throw new Error('useLogStream: Cannot fetch previous entries.\nIt seems there are more entries available, but no cursor is set.\nEnsure you have called `fetchEntries` at least once.'); } if (!state.hasMoreBefore && !(params !== null && params !== void 0 && params.force)) { return; } if (state.topCursor !== null) { fetchLogEntriesBefore(state.topCursor, { size: LOG_ENTRIES_CHUNK_SIZE, extendTo: params === null || params === void 0 ? void 0 : params.extendTo }); } }, [fetchLogEntriesBefore, state.topCursor, state.hasMoreBefore]); const { fetchLogEntriesAfter, isRequestRunning: isLogEntriesAfterRequestRunning, logEntriesAfterSearchResponse$ } = (0, _use_fetch_log_entries_after.useFetchLogEntriesAfter)(commonFetchArguments); (0, _use_observable.useSubscription)(logEntriesAfterSearchResponse$, { next: ({ response: { data, isPartial } }) => { if (data != null && !isPartial) { setState(_prevState => { var _data$hasMoreAfter, _prevState$topCursor, _data$bottomCursor; const prevState = resetOnSuccess ? INITIAL_STATE : _prevState; return { ...(resetOnSuccess ? INITIAL_STATE : prevState), entries: [...prevState.entries, ...data.entries], hasMoreAfter: (_data$hasMoreAfter = data.hasMoreAfter) !== null && _data$hasMoreAfter !== void 0 ? _data$hasMoreAfter : prevState.hasMoreAfter, topCursor: (_prevState$topCursor = prevState.topCursor) !== null && _prevState$topCursor !== void 0 ? _prevState$topCursor : data.topCursor, bottomCursor: (_data$bottomCursor = data.bottomCursor) !== null && _data$bottomCursor !== void 0 ? _data$bottomCursor : prevState.bottomCursor, lastLoadedTime: new Date() }; }); if (resetOnSuccess) { setResetOnSuccess(false); } } } }); const fetchNextEntries = (0, _react.useCallback)(params => { if (state.bottomCursor === null && state.hasMoreAfter) { throw new Error('useLogStream: Cannot fetch next entries. No cursor is set.\nEnsure you have called `fetchEntries` at least once.'); } if (!state.hasMoreAfter && !(params !== null && params !== void 0 && params.force)) { return; } if (state.bottomCursor !== null) { fetchLogEntriesAfter(state.bottomCursor, { size: LOG_ENTRIES_CHUNK_SIZE, extendTo: params === null || params === void 0 ? void 0 : params.extendTo }); } }, [fetchLogEntriesAfter, state.bottomCursor, state.hasMoreAfter]); const fetchEntries = (0, _react.useCallback)(() => { setState(INITIAL_STATE); if (center) { fetchLogEntriesAround(center, LOG_ENTRIES_CHUNK_SIZE); } else { fetchLogEntriesBefore('last', { size: LOG_ENTRIES_CHUNK_SIZE }); } }, [center, fetchLogEntriesAround, fetchLogEntriesBefore, setState]); // Specialized version of `fetchEntries` for streaming. // - Reset the entries _after_ the network request succeeds. // - Ignores `center`. const fetchNewestEntries = (0, _react.useCallback)(() => { setResetOnSuccess(true); fetchLogEntriesBefore('last', { size: LOG_ENTRIES_CHUNK_SIZE }); }, [fetchLogEntriesBefore]); const isReloading = (0, _react.useMemo)(() => isLogEntriesAroundRequestRunning || state.bottomCursor == null && state.topCursor == null && isLogEntriesBeforeRequestRunning, [isLogEntriesAroundRequestRunning, isLogEntriesBeforeRequestRunning, state.bottomCursor, state.topCursor]); const isLoadingMore = (0, _react.useMemo)(() => isLogEntriesBeforeRequestRunning || isLogEntriesAfterRequestRunning, [isLogEntriesAfterRequestRunning, isLogEntriesBeforeRequestRunning]); return { ...state, fetchEntries, fetchNextEntries, fetchPreviousEntries, fetchNewestEntries, isLoadingMore, isReloading }; } const [LogStreamProvider, useLogStreamContext] = (0, _constate.default)(useLogStream); exports.useLogStreamContext = useLogStreamContext; exports.LogStreamProvider = LogStreamProvider;