@rsksmart/rif-storage-pinning
Version:
Application for providing your storage space to other to use in exchange of RIF Tokens
143 lines (142 loc) • 7.62 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MarketplaceEventsProcessor = exports.REORG_OUT_OF_RANGE_EVENT = void 0;
const config_1 = __importDefault(require("config"));
const socket_io_client_1 = __importDefault(require("socket.io-client"));
const feathers_1 = __importDefault(require("@feathersjs/feathers"));
const socketio_client_1 = __importDefault(require("@feathersjs/socketio-client"));
const sequelize_store_1 = require("sequelize-store");
const offer_1 = __importDefault(require("./offer"));
const agreement_1 = __importDefault(require("./agreement"));
const index_1 = require("../index");
const agreement_model_1 = __importDefault(require("../../models/agreement.model"));
const gc_1 = __importDefault(require("../../gc"));
const logger_1 = require("../../logger");
const utils_1 = require("../../utils");
const logger = logger_1.loggingFactory('processor:cache');
const NEW_BLOCK_EVENT = 'newBlock';
exports.REORG_OUT_OF_RANGE_EVENT = 'reorgOutOfRange';
// TODO remove after cache service will be able to filter events for us
function filterCacheEvents(offerId, callback) {
return (event) => __awaiter(this, void 0, void 0, function* () {
if (event.payload.address === offerId || event.payload.offerId === offerId)
yield callback(event);
});
}
class MarketplaceEventsProcessor extends index_1.EventProcessor {
constructor(offerId, manager, options) {
var _a;
super(offerId, options);
this.handlers = [offer_1.default, agreement_1.default];
this.services = {};
this.appResetCallback = options === null || options === void 0 ? void 0 : options.appResetCallback;
const errorHandler = (_a = options === null || options === void 0 ? void 0 : options.errorHandler) !== null && _a !== void 0 ? _a : utils_1.errorHandler;
const deps = {
manager
};
this.processor = filterCacheEvents(this.offerId, errorHandler(this.getProcessor(this.handlers, deps), logger));
this.manager = manager;
this.gcHandler = errorHandler(gc_1.default({ manager: this.manager }), logger_1.loggingFactory('gc'));
}
// eslint-disable-next-line require-await
initialize() {
return __awaiter(this, void 0, void 0, function* () {
if (this.initialized)
throw new Error('Already Initialized');
logger.info('Connecting websocket to ' + config_1.default.get('marketplace.provider'));
// Connect to cache service
const client = feathers_1.default();
const socket = socket_io_client_1.default(config_1.default.get('marketplace.provider'), { transports: ['websocket'] });
client.configure(socketio_client_1.default(socket));
this.services = {
offer: client.service(config_1.default.get('marketplace.offers')),
agreement: client.service(config_1.default.get('marketplace.agreements'))
};
this.newBlockService = client.service(config_1.default.get('marketplace.newBlock'));
this.reorgService = client.service(config_1.default.get('marketplace.reorg'));
this.initialized = true;
logger.info('Services initialized');
});
}
run() {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
if (!this.initialized)
yield this.initialize();
// We run precache on every startup to fetch the latest Agreements state
// The current Agreements get updated thanks to the "upsert" call
yield this.precache();
// Subscribe for new blocks
(_a = this.newBlockService) === null || _a === void 0 ? void 0 : _a.on(NEW_BLOCK_EVENT, this.gcHandler);
// Subscribe for reorgs
(_b = this.reorgService) === null || _b === void 0 ? void 0 : _b.on(exports.REORG_OUT_OF_RANGE_EVENT, (reorgData) => {
if (reorgData.contracts.includes('storage')) {
this.appResetCallback();
}
});
// Subscribe for events
Object
.values(this.services)
.forEach(service => {
service.on('created', this.processor);
service.on('updated', this.processor);
});
logger.info('Subscribed for events');
});
}
precache() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.initialized)
yield this.initialize();
const offer = yield this.services.offer.get(this.offerId).catch(() => undefined);
if (!offer) {
logger.warn(`Offer ${this.offerId} not exist. Pinning will start after offer will be created`);
return;
}
const store = sequelize_store_1.getObject();
if (store.peerId !== (offer === null || offer === void 0 ? void 0 : offer.peerId)) {
logger.error(`PeerId assigned to Offer is not matching the locally available PeerId! Local: ${store.peerId}; Offer: ${offer === null || offer === void 0 ? void 0 : offer.peerId}`);
}
store.totalCapacity = offer === null || offer === void 0 ? void 0 : offer.totalCapacity;
const agreements = yield this.services.agreement.find({ query: { offerId: this.offerId }, paginate: false });
for (const agr of agreements) {
const agreement = new agreement_model_1.default(agr);
yield agreement_model_1.default.upsert(agreement.toJSON());
// Pin agreements
if (agreement.isActive && agreement.hasSufficientFunds) {
yield this.manager.pin(agreement.dataReference, agreement.size, agreement.agreementReference);
}
}
});
}
// eslint-disable-next-line require-await
stop() {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
// Unsubscribe from new blocks event
(_a = this.newBlockService) === null || _a === void 0 ? void 0 : _a.removeListener(NEW_BLOCK_EVENT, this.gcHandler);
// Unsubscribe from reorg event
(_b = this.reorgService) === null || _b === void 0 ? void 0 : _b.removeListener(exports.REORG_OUT_OF_RANGE_EVENT, this.appResetCallback);
// Unsubscribe from events
Object
.values(this.services)
.forEach(service => {
service.removeListener('created', this.processor);
service.removeListener('updated', this.processor);
});
});
}
}
exports.MarketplaceEventsProcessor = MarketplaceEventsProcessor;