"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.browserJourneyEffects = browserJourneyEffects; exports.fetchJourneyStepsEffect = fetchJourneyStepsEffect; var _effects = require("redux-saga/effects"); var _http_error = require("../utils/http_error"); var _api = require("./api"); var _actions = require("./actions"); var _models = require("./models"); var _selectors = require("./selectors"); /* * 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. */ function* browserJourneyEffects() { yield (0, _effects.all)([(0, _effects.fork)(fetchScreenshotBlocks), (0, _effects.fork)(generateBlockStatsOnPut), (0, _effects.fork)(pruneBlockCache)]); } function* fetchBlocks(hashes) { yield (0, _effects.put)((0, _actions.setBlockLoadingAction)(hashes)); const blocks = yield (0, _effects.call)(_api.fetchScreenshotBlockSet, hashes); yield (0, _effects.put)((0, _actions.putBlocksAction)({ blocks })); } function* fetchScreenshotBlocks() { /** * We maintain a list of each hash and how many times it is requested so we can avoid * subsequent re-requests if the block is dropped due to cache pruning. */ yield (0, _effects.takeEvery)(String(_actions.fetchBlocksAction), function* (action) { if (action.payload.length > 0) { yield (0, _effects.put)((0, _actions.updateHitCountsAction)(action.payload)); } }); /** * We do a short delay to allow multiple item renders to queue up before dispatching * a fetch to the backend. */ yield (0, _effects.throttle)(20, String(_actions.fetchBlocksAction), function* () { const { blocks } = yield (0, _effects.select)(_selectors.selectBrowserJourneyState); const toFetch = Object.keys(blocks).filter(hash => { const block = blocks[hash]; return (0, _models.isPendingBlock)(block) && block.status !== 'loading'; }); if (toFetch.length > 0) { yield (0, _effects.fork)(fetchBlocks, toFetch); } }); } function* generateBlockStatsOnPut() { yield (0, _effects.takeEvery)(String(_actions.putBlocksAction), function* (action) { const batchSize = action.payload.blocks.reduce((total, cur) => { return cur.synthetics.blob.length + total; }, 0); yield (0, _effects.put)((0, _actions.putCacheSize)(batchSize)); }); } // 4 MB cap for cache size const MAX_CACHE_SIZE = 4000000; function* pruneBlockCache() { yield (0, _effects.takeEvery)(String(_actions.putCacheSize), function* (_action) { const { cacheSize } = yield (0, _effects.select)(_selectors.selectBrowserJourneyState); if (cacheSize > MAX_CACHE_SIZE) { yield (0, _effects.put)((0, _actions.pruneCacheAction)(cacheSize - MAX_CACHE_SIZE)); } }); } function* fetchJourneyStepsEffect() { const inProgressRequests = new Set(); yield (0, _effects.takeEvery)(String(_actions.fetchJourneyAction.get), function* (action) { try { if (!inProgressRequests.has(action.payload.checkGroup)) { inProgressRequests.add(action.payload.checkGroup); const response = yield (0, _effects.call)(_api.fetchBrowserJourney, action.payload); inProgressRequests.delete(action.payload.checkGroup); yield (0, _effects.put)(_actions.fetchJourneyAction.success(response)); } } catch (e) { inProgressRequests.delete(action.payload.checkGroup); yield (0, _effects.put)(_actions.fetchJourneyAction.fail((0, _http_error.serializeHttpFetchError)(e, action.payload))); } }); }