UNPKG

gemini-core

Version:

Utility which contains common modules for gemini and hermione

115 lines (91 loc) 3.54 kB
'use strict'; const Promise = require('bluebird'); const Pool = require('./pool'); const LimitedUseSet = require('./limited-use-set'); const debug = require('debug'); const {buildCompositeBrowserId} = require('./utils'); module.exports = class CachingPool extends Pool { /** * @constructor * @extends BasicPool * @param {BasicPool} underlyingPool */ constructor(underlyingPool, config, opts) { super(); this.log = debug(`${opts.logNamespace}:pool:caching`); this.underlyingPool = underlyingPool; this._caches = {}; this._config = config; this._logNamespace = opts.logNamespace; } _getCacheFor(id, version) { const compositeId = buildCompositeBrowserId(id, version); this.log(`request for ${compositeId}`); if (!this._caches[compositeId]) { this.log(`init for ${compositeId}`); this._initPool(id, version); } return this._caches[compositeId]; } getBrowser(id, opts = {}) { const {version} = opts; const cache = this._getCacheFor(id, version); const browser = cache.pop(); if (!browser) { this.log(`no cached browser for ${buildCompositeBrowserId(id, version)}, requesting new`); return this.underlyingPool.getBrowser(id, opts); } this.log(`has cached browser ${browser.fullId}`); return browser.reset() .catch((e) => { const reject = Promise.reject.bind(null, e); return this.underlyingPool.freeBrowser(browser) .then(reject, reject); }) .then(() => browser); } _initPool(browserId, version) { const compositeId = buildCompositeBrowserId(browserId, version); const freeBrowser = this.underlyingPool.freeBrowser.bind(this.underlyingPool); const browserConfig = this._config.forBrowser(browserId); this._caches[compositeId] = new LimitedUseSet({ formatItem: (item) => item.fullId, // browser does not get put in a set on first usages, so if // we want to limit it usage to N times, we must set N-1 limit // for the set. useLimit: browserConfig.sessionUseLimit - 1, finalize: freeBrowser, logNamespace: this._logNamespace }); } /** * Free browser * @param {Browser} browser session instance * @param {Object} [options] - advanced options * @param {Boolean} [options.force] - if `true` than browser should * not be cached * @returns {Promise<undefined>} */ freeBrowser(browser, options = {}) { const shouldFreeForNextRequest = () => { const {compositeIdForNextRequest} = options; if (!compositeIdForNextRequest) { return false; } const {hasFreeSlots} = options; const hasCacheForNextRequest = this._caches[options.compositeIdForNextRequest]; return !hasFreeSlots && !hasCacheForNextRequest; }; const force = options.force || shouldFreeForNextRequest(); this.log(`free ${browser.fullId} force=${force}`); if (force) { return this.underlyingPool.freeBrowser(browser); } const cache = this._getCacheFor(browser.id, browser.version); return cache.push(browser); } cancel() { this.log('cancel'); this.underlyingPool.cancel(); } };