feat: 定时任务
This commit is contained in:
@@ -10,6 +10,8 @@ module.exports = () => inject(async function startJob(SysConfig) {
|
|||||||
const jobConn = await mongoose.createConnection(`mongodb://${DB_USER_NAME}:${DB_PASSWD}@${DB_HOST}:${DB_PORT}/${JOB_DB_NAME}`, {
|
const jobConn = await mongoose.createConnection(`mongodb://${DB_USER_NAME}:${DB_PASSWD}@${DB_HOST}:${DB_PORT}/${JOB_DB_NAME}`, {
|
||||||
useNewUrlParser: true,
|
useNewUrlParser: true,
|
||||||
autoReconnect: true,
|
autoReconnect: true,
|
||||||
|
useFindAndModify: false,
|
||||||
|
useUnifiedTopology: true
|
||||||
});
|
});
|
||||||
mylog.info('连接到任务队列数据库成功');
|
mylog.info('连接到任务队列数据库成功');
|
||||||
const Job = new Agenda({ mongo: jobConn });
|
const Job = new Agenda({ mongo: jobConn });
|
||||||
|
|||||||
188
src/jobs/jobs.js
188
src/jobs/jobs.js
@@ -16,97 +16,107 @@
|
|||||||
*/
|
*/
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const User = require('../modules/user/user.model');
|
const User = require('../modules/user/user.model');
|
||||||
|
const Fund = require('../modules/fund/fund.model');
|
||||||
|
const Action = require('../modules/action/action.model');
|
||||||
|
const system = require('../modules/system/system.model');
|
||||||
const { createAction } = require('../modules/action/action.handler');
|
const { createAction } = require('../modules/action/action.handler');
|
||||||
|
const { createNewFund } = require('../modules/fund/fund.handler');
|
||||||
|
|
||||||
|
const tokenReleaseRate = 0.2;
|
||||||
|
|
||||||
|
// fund.option.usedGroupReward : 已领取的社群奖励总额
|
||||||
|
const doReward = async (user, fund) => {
|
||||||
|
// 1.对于充值的fundList的每一项,按照2%进行发放,累加到asset.vic,添加action,类型为1
|
||||||
|
// 2.对于社团成员进行人头数目,按照10vic/人进行奖励,累加到asset.vic,添加action,类型为2
|
||||||
|
if (!user || !fund) return 0;
|
||||||
|
const fundlist = fund.fundList;
|
||||||
|
for (let i = 0, len = fundlist.length; i < len; ++i) {
|
||||||
|
const fund = fundlist[i];
|
||||||
|
const released = fund.releasedAmout || 0;
|
||||||
|
if (released === fund.releasedAmout) {
|
||||||
|
await Fund.findByIdAndUpdate(fund.id, {
|
||||||
|
$set: {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const allInviteReward = (+user.group.length || 0) * 10; // 计算出从开始到现在邀请奖励总额
|
||||||
|
const rewardInvite = allInviteReward - (fund.option.usedGroupReward || 0); // 求增量: 总额 - 已领取总额(fundSum)
|
||||||
|
// 挖矿奖励 = 充值金额奖励 + 社区奖励
|
||||||
|
const rewardMine = +fund.amount * tokenReleaseRate;
|
||||||
|
const reward = rewardMine + rewardInvite;
|
||||||
|
await Fund.findByIdAndUpdate(fund.id, {
|
||||||
|
$inc: {
|
||||||
|
'asset.vic': reward,
|
||||||
|
},
|
||||||
|
$set: {
|
||||||
|
'option.usedGroupReward': rewardInvite, // 本次的奖励值累加到已领取团队奖励总和内
|
||||||
|
'asset.usdt': allInviteReward // 用来记录所有社群奖励总额
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
createAction(1, {
|
||||||
|
userId: fund.userId,
|
||||||
|
tokenType: 'vic',
|
||||||
|
amount: rewardMine,
|
||||||
|
remain: fund.asset
|
||||||
|
}).save();
|
||||||
|
rewardInvite > 0 && createAction(2, {
|
||||||
|
userId: fund.userId,
|
||||||
|
tokenType: 'vic',
|
||||||
|
amount: rewardInvite,
|
||||||
|
remain: fund.asset
|
||||||
|
}).save();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const jobs = [
|
const jobs = [
|
||||||
// {
|
{
|
||||||
// name: 'refreshEstateAndPayBack',
|
name: 'mine',
|
||||||
// processor: async (job, done) => {
|
processor: async (job, done) => {
|
||||||
// //todo: 程序内检查是否可以执行,保证不会启动时错误的自动执行一次
|
//todo: 程序内检查是否可以执行,保证不会启动时错误的自动执行一次
|
||||||
// const now = new Date().getMinutes();
|
const now = new Date();
|
||||||
// if (now > 0 && now < 58) {
|
if (now.getHours() !== 23 && now.getMinutes() < 58) {
|
||||||
// mylog.error('[Schedule Job] 不在合理时间启动...程序结束');
|
mylog.error('[Schedule Job] 不在合理时间启动...程序结束');
|
||||||
// return 0;
|
return 0;
|
||||||
// }
|
}
|
||||||
// mylog.info('开始定时计算作业...');
|
mylog.info('[Schedule Job] 开始定时计算作业...');
|
||||||
// const query = { startTime: +(new Date().getUTCHours()) + 8 + 1 };
|
let currentIndex = await system.findOne({
|
||||||
// const elist = await Estate.find(query).exec();
|
key: 'userIndex4job'
|
||||||
// if (!elist || elist.length <= 0) return 0;
|
}).exec();
|
||||||
// const [ estateSession, userSession, orderSession ] = await Promise.all([
|
if (typeof currentIndex !== 'number') {
|
||||||
// mongoose.startSession(),
|
currentIndex = 0;
|
||||||
// mongoose.startSession(),
|
await new system({
|
||||||
// mongoose.startSession()
|
key: currentIndex
|
||||||
// ]);
|
}).save();
|
||||||
// await Promise.all([
|
}
|
||||||
// estateSession.startTransaction(),
|
|
||||||
// userSession.startTransaction(),
|
// 批量更新,每次十个
|
||||||
// orderSession.startTransaction()
|
const userFundList = await Fund.find().sort('_id').limit(10).skip(currentIndex);
|
||||||
// ]);
|
job.touch();
|
||||||
// job.touch();
|
if (!userFundList || !Array.isArray(userFundList)) return 0;
|
||||||
// for (let i = 0, length = elist.length; i < length; i++) {
|
currentIndex += userFundList.length;
|
||||||
// const estate = elist[i];
|
for (let i = 0, len = userFundList.length; i < len; ++i) {
|
||||||
// const estateId = estate.id;
|
const fundItem = userFundList[i]; // 一条数据库fund表记录
|
||||||
// const userId = estate.currentOwner;
|
const funds = fundItem.fundList;
|
||||||
// // todo: 更精确判读是否要回收地产
|
if (!funds || !Array.isArray(funds)) continue;
|
||||||
// if (!userId) continue;
|
const user = await User.findOne({ id: fundItem.userId }).exec();
|
||||||
// const [ user, order ] = await Promise.all([
|
doReward(user, funds);
|
||||||
// User.findById(userId).exec(),
|
job.touch();
|
||||||
// EstateOrder.findOne({
|
}
|
||||||
// userId,
|
mylog.info('收益计算分配完成');
|
||||||
// estateId,
|
done();
|
||||||
// status: 'holding'
|
},
|
||||||
// }).exec()
|
type: 'every',
|
||||||
// ]);
|
slot: '0 3 * * * *',
|
||||||
// const profit = +estate.price * +estate.profit;
|
priority: 'highest',
|
||||||
// const payback = profit + estate.price;
|
unique: {
|
||||||
// const action = createAction(3, { actor: userId, estate, amount: profit, remain: user.asset });
|
id: 'mine'
|
||||||
// if (!Number.isFinite(payback)) throw new Error('非法的收益数值!');
|
},
|
||||||
// const userOpts = { returnOriginal: false, session: userSession };
|
skipImmediate: true,
|
||||||
// const orderOpts = { returnOriginal: false, session: orderSession };
|
timezone: "ETC/GMT+8"
|
||||||
// const estateOpts = { returnOriginal: false, session: estateSession };
|
}
|
||||||
// try {
|
|
||||||
// await Promise.all([
|
|
||||||
// user.increase('profit', payback, userOpts),
|
|
||||||
// estate.sell(estateOpts),
|
|
||||||
// order.finish(orderOpts),
|
|
||||||
// action.save()
|
|
||||||
// ]);
|
|
||||||
// await Promise.all([
|
|
||||||
// userSession.commitTransaction(),
|
|
||||||
// orderSession.commitTransaction(),
|
|
||||||
// estateSession.commitTransaction()
|
|
||||||
// ]);
|
|
||||||
// } catch (error) {
|
|
||||||
// mylog.error(error);
|
|
||||||
// await Promise.all([
|
|
||||||
// action.remove(),
|
|
||||||
// userSession.abortTransaction(),
|
|
||||||
// orderSession.abortTransaction(),
|
|
||||||
// estateSession.abortTransaction()
|
|
||||||
// ]);
|
|
||||||
// } finally {
|
|
||||||
// await Promise.all([
|
|
||||||
// userSession.endSession(),
|
|
||||||
// orderSession.endSession(),
|
|
||||||
// estateSession.endSession()
|
|
||||||
// ]);
|
|
||||||
// }
|
|
||||||
// job.touch();
|
|
||||||
// }
|
|
||||||
// mylog.info('收益计算分配完成');
|
|
||||||
// done();
|
|
||||||
// },
|
|
||||||
// type: 'every',
|
|
||||||
// // 写成 '*/59 * * * *' 会出现59分执行一次,下一小时的0分再执行一次
|
|
||||||
// // 写成 '*/59 * * * *' 是每59
|
|
||||||
// // 最差的解决方案是 在58分执行
|
|
||||||
// slot: '59 */1 * * *', // 59th minute per hour
|
|
||||||
// priority: 'highest',
|
|
||||||
// unique: {
|
|
||||||
// id: 'payback001'
|
|
||||||
// },
|
|
||||||
// skipImmediate: true,
|
|
||||||
// timezone: "ETC/GMT+8"
|
|
||||||
// }
|
|
||||||
];
|
];
|
||||||
function mountJobs (Job) {
|
function mountJobs (Job) {
|
||||||
jobs.map(jobConfig => {
|
jobs.map(jobConfig => {
|
||||||
|
|||||||
Reference in New Issue
Block a user