@rsksmart/rif-storage-pinning
Version:
Application for providing your storage space to other to use in exchange of RIF Tokens
110 lines (109 loc) • 5.14 kB
JavaScript
;
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.collectDirectAddresses = exports.collectPinsClosure = void 0;
const config_1 = __importDefault(require("config"));
const parse_duration_1 = __importDefault(require("parse-duration"));
const agreement_model_1 = __importDefault(require("./models/agreement.model"));
const sequelize_1 = require("sequelize");
const logger_1 = require("./logger");
const communication_1 = require("./communication");
const definitions_1 = require("./definitions");
const errors_1 = require("./errors");
const direct_address_model_1 = __importDefault(require("./models/direct-address.model"));
const utils_1 = require("./utils");
const logger = logger_1.loggingFactory('gc');
/**
* This is a closure that garbage-collects pins of expired Agreements.
*
* When first detects an Agreement to have no funds it saves the block number at what it was detected.
* Then after number of blocks specified for confirmations it actualy unpins the data.
*
* This is in order to handle case when reorg happens and the DepositFunds event is emitted in the
* confirmation range.
*
* @param options
*/
function collectPinsClosure(options) {
return (block) => __awaiter(this, void 0, void 0, function* () {
var _a;
logger.verbose('Running pinning GC');
const nonExpiredAgreements = yield agreement_model_1.default.findAll({ where: { expiredAtBlockNumber: null, isActive: true } });
for (const agreement of nonExpiredAgreements) {
if (!agreement.hasSufficientFunds) {
logger.info(`Marking agreement ${agreement.agreementReference} to be collected at block ${block.number}.`);
agreement.expiredAtBlockNumber = block.number;
yield agreement.save();
}
}
const agreementsToUnpins = yield agreement_model_1.default.findAll({
where: {
expiredAtBlockNumber: {
[sequelize_1.Op.lte]: block.number - config_1.default.get('blockchain.eventsEmitter.confirmations')
},
isActive: true
}
});
for (const agreement of agreementsToUnpins) {
if (agreement.hasSufficientFunds) { // Agreement received funds in meanwhile, lets continue!
agreement.expiredAtBlockNumber = null;
}
else { // Agreement is still without funds!
logger.info(`Unpinning agreement ${agreement.agreementReference}.`);
try {
yield ((_a = options === null || options === void 0 ? void 0 : options.manager) === null || _a === void 0 ? void 0 : _a.unpin(agreement.dataReference));
}
catch (e) {
if (e.code === errors_1.NotPinnedError.code) {
logger.info(`Data reference ${agreement.dataReference} was already removed prior our GC run!`);
}
else {
throw e;
}
}
yield communication_1.broadcast(definitions_1.MessageCodesEnum.I_AGREEMENT_EXPIRED, { agreementReference: agreement.agreementReference });
agreement.isActive = false;
}
yield agreement.save();
}
});
}
exports.collectPinsClosure = collectPinsClosure;
function collectDirectAddresses() {
return () => __awaiter(this, void 0, void 0, function* () {
logger.info('In collect Direct Addresses');
if (!config_1.default.has('directAddress.ttl')) {
logger.error('ttl for "directAddress" not provided');
}
const ttl = parse_duration_1.default(config_1.default.get('directAddress.ttl'));
if (!ttl) {
throw new Error('Invalid Direct Address ttl value');
}
yield direct_address_model_1.default.destroy({
where: {
createdAt: {
[sequelize_1.Op.lte]: new Date(Date.now() - ttl)
}
}
});
});
}
exports.collectDirectAddresses = collectDirectAddresses;
function default_1(options) {
return utils_1.composeGc([
collectPinsClosure(options),
collectDirectAddresses()
]);
}
exports.default = default_1;