aozhiwei ba2e5138ed 1
2022-02-15 18:09:18 +08:00

163 lines
4.0 KiB
JavaScript

const util = require('util');
const utils = require('./utils');
const dbhelper = require("./dbhelper");
const log = require("./log");
const dblog = require("./dblog");
const bc = require('./blockchain');
const C = require('./C');
class ContractExecutor {
constructor() {
this.instanceName = '';
this.doSuspend = null;
this.getLogKey = null;
this.getLogData = null;
this.getPrepareBlockNumber = null;
this.getSuccessBlockNumber = null;
this.getSyncCount = null;
this.searchLogClass = '';
this.eventName = '';
this.eventFilter = null;
this.syncLogClass = '';
this.methodName = '';
this.methodArgs = [];
this.syncDbLogClass = '';
this.onResetState = null;
this.onSearchSuccess = null;
this.onSyncSuccess = null;
}
init() {
this.instance = bc[this.instanceName];
this.method = this.instance.methods[this.methodName];
}
async execute() {
let tryCount = 0;
let confirmed = false;
do {
await this.sync();
confirmed = await this.confirm();
if (!confirmed) {
++tryCount;
await this.onResetState();
await utils.sleep(utils.randRange(1500, 4000));
}
} while (tryCount < 3 && !confirmed && this.getSyncCount() < 3);
return confirmed;
}
async sync() {
await bc.mustBeActive();
const found = await this.bcSearch();
if (!found) {
const ok = await this.bcSync();
if (!ok) {
this.doSuspend(this.syncLogClass, '');
return;
}
}
}
async confirm() {
while (true) {
if (bc.isComfirmed(this.getSuccessBlockNumber())) {
const found = await this.bcSearch();
return found;
break;
}
await utils.sleep(1000 * 3);
}
return false;
}
async bcSearch() {
if (this.getPrepareBlockNumber() <= 0) {
return false;
}
let events = [];
while (true) {
try {
const fromBlock = Math.max(this.getPrepareBlockNumber() - 1000, 0);
events = await this.instance.getPastEvents(
this.eventName,
{
fromBlock: fromBlock,
toBlock: fromBlock + 5000 - 1,
filter: this.eventFilter
});
break;
} catch (err) {
log.warning(
util.format('%s getPastEvents data:%s err:%s',
this.searchLogClass,
utils.jsonEncode(this.getLogData()),
err
));
}
await utils.sleep(1000 * 3);
}
if (events.length > 0) {
const blockNumber = events[0]['blockNumber'];
if (!blockNumber) {
await this.doSuspend(this.searchLogClass, 'blocNumber is empty');
return false;
}
await this.onSearchSuccess(events[0]);
}
return events.length > 0;
}
async bcSync() {
await bc.mustBeActive();
const currBlockNumber = bc.getCurrBlockNumber();
const doSync = async() => {
let result = null;
try {
await dblog.addLog(
this.syncDbLogClass,
'prepare',
this.getLogKey(),
utils.jsonEncode(this.getLogData()));
result = await this.method(this.methodArgs).send({gas: 1000000});
await dblog.addLog(
this.syncDbLogClass,
'success',
this.getOrderId(),
utils.jsonEncode(this.getLogData()),
utils.jsonEncode(result));
await this.onSyncSuccess(result);
} catch (err) {
await dblog.addLog(
this.syncDbLogClass,
'failed',
this.getLogKey(),
utils.jsonEncode(this.getLogData()),
err);
await this.doSuspend(this.syncLogClass, err);
}
return result;
};
try {
const result = await doSync();
return true;
} catch (err) {
log.warning(
util.format('%s end data:%s err:%s',
this.syncLogClass,
utils.jsonEncode(this.getLogData()),
err
)
);
}
return false;
}
};
exports.ContractExecutor = ContractExecutor;