lisk-framework
Version:
Lisk blockchain application platform
80 lines • 3.42 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Synchronizer = void 0;
const assert = require("assert");
const lisk_utils_1 = require("@liskhq/lisk-utils");
const utils = require("./utils");
class Synchronizer {
constructor({ logger, chainModule, blockExecutor, mechanisms = [] }) {
assert(Array.isArray(mechanisms), 'mechanisms should be an array of mechanisms');
this.mechanisms = mechanisms;
this.logger = logger;
this.chainModule = chainModule;
this.blockExecutor = blockExecutor;
this._checkMechanismsInterfaces();
this._mutex = new lisk_utils_1.jobHandlers.Mutex();
}
async init() {
const isEmpty = await this.chainModule.dataAccess.isTempBlockEmpty();
if (!isEmpty) {
try {
await utils.restoreBlocksUponStartup(this.logger, this.chainModule, this.blockExecutor);
}
catch (err) {
this.logger.error({ err: err }, 'Failed to restore blocks from temp table upon startup');
}
}
}
async run(receivedBlock, peerId) {
if (this._mutex.isLocked()) {
this.logger.debug('Synchronizer is already running.');
return;
}
await this._mutex.runExclusive(async () => {
assert(receivedBlock, 'A block must be provided to the Synchronizer in order to run');
this.logger.info({
blockId: receivedBlock.header.id,
height: receivedBlock.header.height,
generator: receivedBlock.header.generatorAddress.toString('hex'),
}, 'Starting synchronizer');
this.blockExecutor.validate(receivedBlock);
const validMechanism = await this._determineSyncMechanism(receivedBlock, peerId);
if (!validMechanism) {
this.logger.info({ blockId: receivedBlock.header.id }, 'Syncing mechanism could not be determined for the given block');
return;
}
this.logger.info(`Triggering: ${validMechanism.constructor.name}`);
await validMechanism.run(receivedBlock, peerId);
this.logger.info({
lastBlockHeight: this.chainModule.lastBlock.header.height,
lastBlockID: this.chainModule.lastBlock.header.id,
mechanism: validMechanism.constructor.name,
}, 'Synchronization finished.');
});
}
get isActive() {
return this._mutex.isLocked();
}
async stop() {
for (const mechanism of this.mechanisms) {
mechanism.stop();
}
await this._mutex.acquire();
}
async _determineSyncMechanism(receivedBlock, peerId) {
for (const mechanism of this.mechanisms) {
if (await mechanism.isValidFor(receivedBlock, peerId)) {
return mechanism;
}
}
return undefined;
}
_checkMechanismsInterfaces() {
for (const mechanism of this.mechanisms) {
assert(typeof mechanism.isValidFor === 'function', `Mechanism ${mechanism.constructor.name} should implement "isValidFor" method`);
assert(typeof mechanism.run === 'function', `Mechanism ${mechanism.constructor.name} should implement "run" method`);
}
}
}
exports.Synchronizer = Synchronizer;
//# sourceMappingURL=synchronizer.js.map