UNPKG

af-consul

Version:

A highly specialized function library

141 lines 6.73 kB
/* eslint-disable no-console */ // noinspection JSUnusedGlobalSymbols import { cyan, green, magenta, red, reset } from '../lib/color'; import loggerStub from '../lib/logger-stub'; import { getConsulApiCached } from '../index'; import { sleep } from '../lib/utils'; import { DEBUG, CONSUL_AP_UPDATE_TIMEOUT_MILLIS } from '../constants'; const PREFIX = 'AP-UPDATER'; const dbg = { on: /\bAP-UPDATER\*?/i.test(DEBUG) || DEBUG === '*' }; const debug = (msg) => { if (dbg.on) { console.log(`${magenta}${PREFIX}${reset}: ${msg}`); } }; const UPDATE_INTERVAL_IF_CONSUL_REGISTER_SUCCESS_MILLIS = Number(process.env.UPDATE_INTERVAL_IF_CONSUL_REGISTER_SUCCESS_MILLIS) || (2 * 60000); // A stub in case such a function is not set for the access point in the configuration function retrieveProps(accessPoint, host, meta) { const port = Number(meta === null || meta === void 0 ? void 0 : meta.port) || accessPoint.port; return { host, port }; } // Служит для исключения повторного опроса consulID в пределах одного цикла updateAccessPoints let oneUpdateCache = {}; export async function updateAccessPoint(clOptions, accessPoint) { var _a, _b, _c, _d, _e, _f, _g, _h; if (!accessPoint.updateIntervalIfSuccessMillis) { accessPoint.updateIntervalIfSuccessMillis = UPDATE_INTERVAL_IF_CONSUL_REGISTER_SUCCESS_MILLIS; } if (Date.now() - (accessPoint.lastSuccessUpdate || 0) < accessPoint.updateIntervalIfSuccessMillis) { return 0; } const { consulServiceName } = accessPoint; const CONSUL_ID = `${cyan}${consulServiceName}${reset}`; let result = oneUpdateCache[consulServiceName]; if (result) { if (result.length) { // Точка доступа уже опрошена в этом цикле и она была недоступна return 0; } // Точка доступа еще опрошена в этом цикле и есть сведения по ней. В этом просе будут взяты другие метаданные, нежели в предыдущем updateAccessPoint } else { // Точка доступа еще не опрошена в этом цикле const consulApi = await getConsulApiCached(clOptions); if (!consulApi) { (_a = clOptions.logger) === null || _a === void 0 ? void 0 : _a.warn(`${PREFIX}: Failed to get consul API`); return -2; } debug(`${reset}Polling ${CONSUL_ID}`); result = await consulApi.consulHealthService({ options: { service: consulServiceName, passing: true } }); oneUpdateCache[consulServiceName] = result; } const { Address: host, Meta: meta } = ((_b = result === null || result === void 0 ? void 0 : result[0]) === null || _b === void 0 ? void 0 : _b.Service) || {}; if (!host) { (_c = clOptions.logger) === null || _c === void 0 ? void 0 : _c.warn(`${red}There is no information for ${CONSUL_ID}`); accessPoint.lastSuccessUpdate = 0; const wasReachable = accessPoint.isReachable; accessPoint.isReachable = false; if (wasReachable) { (_d = clOptions.em) === null || _d === void 0 ? void 0 : _d.emit('access-point-updated', { accessPoint, changes: [['isReachable', true, false]] }); } return -1; } accessPoint.isReachable = true; accessPoint.lastSuccessUpdate = Date.now(); // If the retrieveProps function is not set for the access point in the configuration, use the stub if (typeof accessPoint.retrieveProps !== 'function') { accessPoint.retrieveProps = retrieveProps.bind(null, accessPoint); } const properties = accessPoint.retrieveProps(host, meta); const changes = (_g = (_f = (_e = accessPoint.setProps) === null || _e === void 0 ? void 0 : _e.call(accessPoint, properties)) === null || _f === void 0 ? void 0 : _f.getChanges) === null || _g === void 0 ? void 0 : _g.call(_f); if (changes === null || changes === void 0 ? void 0 : changes.length) { accessPoint.meta = meta; (_h = clOptions.em) === null || _h === void 0 ? void 0 : _h.emit('access-point-updated', { accessPoint, changes }); } else { debug(`${green}The data is up-to-date ${CONSUL_ID}`); } return 1; } export async function updateAccessPoints(clOptions) { var _a, _b; const accessPoints = Object.values(clOptions.config.accessPoints).filter((ap) => (ap === null || ap === void 0 ? void 0 : ap.isAP) && !ap.noConsul); const result = []; for (let i = 0; i < accessPoints.length; i++) { const accessPoint = accessPoints[i]; // eslint-disable-next-line no-await-in-loop const res = await updateAccessPoint(clOptions, accessPoint); result.push(res); } const updatedCount = result.filter((v) => v > 0); if (updatedCount.length) { (_a = clOptions.logger) === null || _a === void 0 ? void 0 : _a.silly(`${PREFIX}: updated ${updatedCount.length} access point(s)`); (_b = clOptions.em) === null || _b === void 0 ? void 0 : _b.emit('access-points-updated'); } return !!updatedCount; } export const accessPointsUpdater = { isStarted: false, isAnyUpdated: false, _timerId: setTimeout(() => null, 0), _logger: loggerStub, start(clOptions, updateInterval = 10000) { if (this.isStarted) { return 0; } this._logger = clOptions.logger || loggerStub; const doLoop = async () => { var _a; try { oneUpdateCache = {}; const isAnyUpdated = await updateAccessPoints(clOptions); if (isAnyUpdated) { this.isAnyUpdated = true; } } catch (err) { (_a = this._logger) === null || _a === void 0 ? void 0 : _a.error(err); } clearTimeout(this._timerId); this._timerId = setTimeout(doLoop, updateInterval); }; doLoop().then((r) => r); this.isStarted = true; this._logger.info('Access point updater started'); return 1; }, async waitForAnyUpdated(timeout = CONSUL_AP_UPDATE_TIMEOUT_MILLIS) { const start = Date.now(); while (!this.isAnyUpdated && (Date.now() - start < timeout)) { // eslint-disable-next-line no-await-in-loop await sleep(100); } return this.isAnyUpdated; }, stop() { clearTimeout(this._timerId); this.isStarted = false; this._logger.info('Access point updater stopped'); }, }; //# sourceMappingURL=access-points-updater.js.map