bsp-network
Version:
SDK for writing node.js applications to interact with bsp network. This package encapsulates the APIs to connect to a bsp network, submit transactions and perform queries against the ledger.
128 lines • 4.71 kB
JavaScript
"use strict";
/**
* Copyright 2020 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
const Logger = require("../../logger");
const GatewayUtils = require("../gatewayutils");
const asyncnotifier_1 = require("./asyncnotifier");
const filteredblockeventfactory_1 = require("./filteredblockeventfactory");
const fullblockeventfactory_1 = require("./fullblockeventfactory");
const orderedblockqueue_1 = require("./orderedblockqueue");
const privateblockeventfactory_1 = require("./privateblockeventfactory");
const Long = require("long");
const logger = Logger.getLogger('BlockEventSource');
const defaultBlockType = 'filtered';
class BlockEventSource {
constructor(eventServiceManager, options = {}) {
this.listeners = new Set();
this.started = false;
this.eventServiceManager = eventServiceManager;
this.blockQueue = this.newBlockQueue(options);
this.asyncNotifier = new asyncnotifier_1.AsyncNotifier(this.blockQueue.getNextBlock.bind(this.blockQueue), this.notifyListeners.bind(this));
this.blockType = options.type || defaultBlockType;
}
async addBlockListener(listener) {
this.listeners.add(listener);
await this.start();
return listener;
}
removeBlockListener(listener) {
this.listeners.delete(listener);
}
close() {
var _a;
this.unregisterListener();
(_a = this.eventService) === null || _a === void 0 ? void 0 : _a.close();
this.started = false;
}
newBlockQueue(options) {
const startBlock = options.startBlock ? Long.fromValue(options.startBlock) : undefined;
return new orderedblockqueue_1.OrderedBlockQueue(startBlock);
}
async start() {
if (this.started) {
return;
}
this.started = true;
try {
this.eventService = this.eventServiceManager.newDefaultEventService();
this.registerListener(); // Register before start so no events are missed
await this.startEventService();
}
catch (error) {
logger.error('Failed to start event service', error);
this.close();
}
}
registerListener() {
const callback = this.blockEventCallback.bind(this);
const options = {
startBlock: this.getNextBlockNumber(),
unregister: false
};
this.eventListener = this.eventService.registerBlockListener(callback, options);
}
unregisterListener() {
var _a;
try {
(_a = this.eventListener) === null || _a === void 0 ? void 0 : _a.unregisterEventListener();
}
catch (error) {
logger.warn('Failed to unregister listener', error);
}
}
async startEventService() {
const options = {
blockType: this.blockType,
startBlock: this.getNextBlockNumber()
};
await this.eventServiceManager.startEventService(this.eventService, options);
}
blockEventCallback(error, event) {
if (error) {
this.close();
setImmediate(() => this.start()); // Must schedule after current event loop to avoid recursion in event service notification
}
else {
this.onBlockEvent(event);
}
}
onBlockEvent(eventInfo) {
const blockEvent = this.newBlockEvent(eventInfo);
this.blockQueue.addBlock(blockEvent);
if (this.blockQueue.size() > 0) {
this.asyncNotifier.notify();
}
}
newBlockEvent(eventInfo) {
if (this.blockType === 'filtered') {
return filteredblockeventfactory_1.newFilteredBlockEvent(eventInfo);
}
else if (this.blockType === 'full') {
return fullblockeventfactory_1.newFullBlockEvent(eventInfo);
}
else if (this.blockType === 'private') {
return privateblockeventfactory_1.newPrivateBlockEvent(eventInfo);
}
else {
throw new Error('Unsupported event type: ' + this.blockType);
}
}
async notifyListeners(event) {
const promises = Array.from(this.listeners).map((listener) => listener(event));
const results = await GatewayUtils.allSettled(promises);
for (const result of results) {
if (result.status === 'rejected') {
logger.warn('Error notifying listener', result.reason);
}
}
}
getNextBlockNumber() {
return this.blockQueue.getNextBlockNumber();
}
}
exports.BlockEventSource = BlockEventSource;
//# sourceMappingURL=blockeventsource.js.map