import { getModelForClass, modelOptions, mongoose, prop, Severity } from '@typegoose/typegoose' import { dbconn } from 'decorators/dbconn' import logger from 'logger/logger' import { InfoSvr } from 'service/info.service' import { BaseModule } from './Base' import { ReqTaskStatus, RequestTask } from './RequestTask' export enum TaskStatus { NOTSTART = 0, PEDING = 1, SUCCESS = 2, PART_ERROR = 8, ERROR = 9, } @dbconn() @modelOptions({ schemaOptions: { collection: 'chain_task', timestamps: true }, options: { allowMixed: Severity.ALLOW }, }) export class ChainTaskClass extends BaseModule { @prop({ required: true }) public taskId!: string @prop({ type: mongoose.Schema.Types.Mixed }) public taskData: any @prop({ enum: TaskStatus, default: TaskStatus.NOTSTART }) public status: TaskStatus @prop() public startTime: number @prop() public endTime: number @prop({ required: true, default: true }) public newRecord: boolean @prop({ required: true, default: false }) public allEnd: boolean @prop({ required: true, default: 0 }) public successCount: number @prop({ required: true, default: 0 }) public errorCount: number @prop({ type: String, required: true, default: [] }) public tasks!: Array /** * 检查是否所有的任务都已完成(成功或重试次数达到上限) * 调用时机 * 1. 每个 request task 成功 * 2. 每个 request task 重试达到预设次数 * @param chainTaskId */ public static async checkStatus(chainTaskId: string) { let record = await ChainTask.findById(chainTaskId) let sCount = 0 let errCount = 0 let hashList: string[] = [] for (let subId of record.tasks) { let subData = await RequestTask.findById(subId) if (subData.status === ReqTaskStatus.SUCCESS) { sCount += 1 } else if (subData.status === ReqTaskStatus.ERROR) { errCount += 1 } hashList.push(subData.txHash) } record.successCount = sCount record.errorCount = errCount if (sCount === record.tasks.length) { record.status = TaskStatus.SUCCESS record.allEnd = true } else { record.allEnd = false if (record.status === TaskStatus.NOTSTART && sCount > 0) { record.status = TaskStatus.PEDING } else if (errCount === record.tasks.length) { record.status = TaskStatus.ERROR record.allEnd = true } else if (errCount + sCount === record.tasks.length) { record.status = TaskStatus.PART_ERROR record.allEnd = true } } await record.save() if (record.allEnd) { setImmediate(async function () { try { let result = await new InfoSvr().reportTaskResult({ id: record.taskId, result: record.status, successCount: record.successCount, errorCount: record.errorCount, hashList, }) // logger.log(result) } catch (err) { logger.log(err) } }) } } public static async allUnFinishedTask() { return ChainTask.find({ allEnd: false }) } } export const ChainTask = getModelForClass(ChainTaskClass, { existingConnection: ChainTaskClass['db'] })