UNPKG

bitcore-node

Version:

A blockchain indexing node with extended capabilities using bitcore

180 lines 6.88 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.P2P = exports.BaseP2PWorker = exports.P2pManager = void 0; const os = __importStar(require("os")); const logger_1 = __importDefault(require("../logger")); const state_1 = require("../models/state"); const utils_1 = require("../utils"); const config_1 = require("./config"); class P2pManager { constructor({ configService = config_1.Config } = {}) { this.workerClasses = {}; this.configService = configService; this.workers = new Array(); } register(chain, network, worker) { this.workerClasses[chain] = this.workerClasses[chain] || {}; this.workerClasses[chain][network] = worker; } get(chain, network) { return this.workerClasses[chain][network]; } async stop() { logger_1.default.info('Stopping P2P Manager'); for (const worker of this.workers) { await worker.stop(); } this.workers = []; } async start() { if (this.configService.isDisabled('p2p')) { logger_1.default.info('Disabled P2P Manager'); return; } logger_1.default.info('Starting P2P Manager'); for (let chainNetwork of config_1.Config.chainNetworks()) { const { chain, network } = chainNetwork; const chainConfig = config_1.Config.chainConfig(chainNetwork); if ((chainConfig.chainSource && chainConfig.chainSource !== 'p2p') || chainConfig.disabled) { continue; } logger_1.default.info(`Starting P2P worker ${chain}:${network}`); const p2pWorker = new this.workerClasses[chain][network]({ chain, network, chainConfig }); this.workers.push(p2pWorker); try { p2pWorker.start(); } catch (e) { logger_1.default.error('P2P Worker %o:%o died: %o', chain, network, e.stack || e.message || e); } } } } exports.P2pManager = P2pManager; class BaseP2PWorker { constructor(params) { this.params = params; this.lastHeartBeat = ''; this.queuedRegistrations = new Array(); this.stopping = false; this.chain = ''; this.network = ''; this.isSyncingNode = false; } async start() { } async stop() { } async sync() { } getIsSyncingNode() { if (!this.lastHeartBeat) { return false; } const [hostname, pid, timestamp] = this.lastHeartBeat.split(':'); const hostNameMatches = hostname === os.hostname(); const pidMatches = pid === process.pid.toString(); const timestampIsFresh = Date.now() - parseInt(timestamp) < 5 * 60 * 1000; const amSyncingNode = hostNameMatches && pidMatches && timestampIsFresh; return amSyncingNode; } async waitTilSync() { while (true) { if (this.isSyncingNode) { return; } await (0, utils_1.wait)(500); } } async refreshSyncingNode() { while (!this.stopping) { const wasSyncingNode = this.getIsSyncingNode(); this.lastHeartBeat = await state_1.StateStorage.getSyncingNode({ chain: this.chain, network: this.network }); const nowSyncingNode = this.getIsSyncingNode(); this.isSyncingNode = nowSyncingNode; if (wasSyncingNode && !nowSyncingNode) { throw new Error('Syncing Node Renewal Failure'); } if (!wasSyncingNode && nowSyncingNode) { logger_1.default.info(`This worker is now the syncing node for ${this.chain} ${this.network}`); this.sync(); } if (!this.lastHeartBeat || this.getIsSyncingNode()) { this.registerSyncingNode({ primary: true }); } else { logger_1.default.info('Another node is the primary syncing node'); this.registerSyncingNode({ primary: false }); } await (0, utils_1.wait)(500); } } async registerSyncingNode({ primary }) { const lastHeartBeat = this.lastHeartBeat; const queuedRegistration = setTimeout(() => { state_1.StateStorage.selfNominateSyncingNode({ chain: this.chain, network: this.network, lastHeartBeat }); }, primary ? 0 : 5 * 60 * 1000); this.queuedRegistrations.push(queuedRegistration); } async unregisterSyncingNode() { await (0, utils_1.wait)(1000); try { this.lastHeartBeat = await state_1.StateStorage.getSyncingNode({ chain: this.chain, network: this.network }); if (this.getIsSyncingNode()) { await state_1.StateStorage.selfResignSyncingNode({ chain: this.chain, network: this.network, lastHeartBeat: this.lastHeartBeat }); } } catch (e) { logger_1.default.warn('Issue unregistering'); logger_1.default.error('%o', e); } } } exports.BaseP2PWorker = BaseP2PWorker; exports.P2P = new P2pManager(); //# sourceMappingURL=p2p.js.map