This commit is contained in:
chaosBreaking
2019-10-15 14:21:46 +08:00
parent 858eea41ec
commit cd7d093fc7
2 changed files with 222 additions and 1 deletions

View File

@@ -21,6 +21,7 @@ const Action = require('../modules/action/action.model');
const system = require('../modules/system/system.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 { createNewFund } = require('../modules/fund/fund.handler');
const exec = require('child_process').exec;
const tokenReleaseRate = 0.02; const tokenReleaseRate = 0.02;
async function awardMine(user, fund) { async function awardMine(user, fund) {
@@ -148,10 +149,17 @@ async function confirm (job = mock, done = mock) {
}); });
return typeof done === 'function' && done('矿晶确认完成'); return typeof done === 'function' && done('矿晶确认完成');
} }
async function mineJob (job = mock, done = mock) {
exec('node ./src/jobs/mine.js');
mylog.info('挖矿程序执行完毕');
typeof done === 'function' && done('挖矿程序执行完毕');
}
const jobs = [ const jobs = [
// { // {
// name: 'mine', // name: 'mine',
// processor: mine, // processor: mineJob,
// type: 'every', // type: 'every',
// slot: '0 0 3 * * *', // slot: '0 0 3 * * *',
// priority: 'highest', // priority: 'highest',
@@ -161,6 +169,18 @@ const jobs = [
// skipImmediate: true, // skipImmediate: true,
// timezone: "ETC/GMT+8" // timezone: "ETC/GMT+8"
// }, // },
{
name: 'mine',
processor: mineJob,
type: 'every',
slot: '0 0 2 * * *',
priority: 'highest',
unique: {
id: 'mine'
},
skipImmediate: true,
timezone: "ETC/GMT+8"
},
{ {
name: 'confirm', name: 'confirm',
processor: confirm, processor: confirm,

201
src/jobs/mine.js Normal file
View File

@@ -0,0 +1,201 @@
'use strict';
const bunyan = require('bunyan');
const PrettyStream = require('bunyan-pretty-colors');
const path = require('path');
const fs = require('fs');
const prettyStdOut = new PrettyStream();
prettyStdOut.pipe(process.stdout);
if (!fs.existsSync('minelog')) {
fs.mkdirSync('minelog');
}
const logger = function (option) {
option = option || {};
return bunyan.createLogger({
name: "log",
src: false,
streams: [
{
level: 'info',
stream: prettyStdOut
},
{
level: 'info',
type: 'rotating-file',
path: path.join(option.root, option.file || 'info.log'),
period: '1d', // daily rotation
count: 365 // keep 30 days
}
]
});
};
const filename = 'minelog' + new Date().getFullYear() + new Date().getMonth() + new Date().getDate();
const mylog = logger(({ root: 'minelog', file: filename }));
const mongoose = require('mongoose');
const User = require('./src/modules/user/user.model');
const Fund = require('./src/modules/fund/fund.model');
const system = require('./src/modules/system/system.model');
const { createAction } = require('./src/modules/action/action.handler');
const tokenReleaseRate = 0.02;
const inviteReward = 2.5;
async function awardMine(user, fund) {
if (!user || !fund || fund.fundList.length === 0) return 0;
let sum = 0;
for (let i = 0, len = fund.fundList.length; i < len; ++i) {
const released = fund.releasedAmout || 0;
if (released === fund.releasedAmout) {
console.log('矿晶失效,开始标记');
await Fund.findByIdAndUpdate(fund.id, {
$set: {
[`fundList.${i}.status`]: 2 //标记失效
}
});
return 0;
}
sum += +fund.fundList[i].amount * tokenReleaseRate;
}
return sum.toFixed(2);
}
function awardInvite(user, fund) {
const follerNum = user.group.length || 0;
const hasAwardFoller = fund.option && fund.option.usedGroupReward / 10 || 0; // 求增量: 总额 - 已领取总额(fundSum)
const newFoller = follerNum - hasAwardFoller;
if (newFoller < 0) return 0;
// 挖矿奖励 = 充值金额奖励 + 社区奖励
return (newFoller * inviteReward).toFixed(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 rewardMine = await awardMine(user, fund);
// const rewardInvite = awardInvite(user, fund);
const rewardInvite = 0;
const reward = +rewardMine + rewardInvite;
console.log('挖矿奖励: ', rewardMine);
console.log('社群奖励: ', rewardInvite);
reward && await Fund.findByIdAndUpdate(fund.id, {
$inc: {
'asset.vic': reward,
'asset.usdt': rewardInvite, // 用来记录所有社群奖励总额
},
$set: {
'option.newFoller': rewardInvite / 5,
'option.usedGroupReward': rewardInvite, // 本次的奖励值累加到已领取团队奖励总和内
'lastMine': new Date().toISOString()
}
}).then(() => {
rewardMine > 0 && createAction(1, {
userId: user.id,
tokenType: 'vic',
amount: rewardMine,
remain: fund.asset
}).save();
rewardInvite > 0 && createAction(2, {
userId: user.id,
tokenType: 'vic',
amount: rewardInvite,
remain: fund.asset
}).save();
});
};
const mock = {
touch: () => {console.log('-----------------\n');},
done: () => {console.log('done');},
};
async function mine (job = mock, done = mock) {
//todo: 程序内检查是否可以执行,保证不会启动时错误的自动执行一次
mylog.info('[Schedule Job] 挖矿程序 开始定时计算作业...');
let currentIndex = await system.findOne({
key: 'userIndex4job'
}).exec();
currentIndex = currentIndex.value;
if (typeof currentIndex !== 'number') {
currentIndex = 0;
await new system({
key: 'userIndex4job',
value: currentIndex
}).save();
}
let allFundNum = await Fund.countDocuments();
await system.updateOne({
key: 'restFundNum',
}, {
value: allFundNum
});
// 批量更新,每次十个
for (; currentIndex < allFundNum;) {
const userFundList = await Fund.find().sort('_id').limit(10).skip(currentIndex);
typeof job.touch === 'function' && job.touch();
if (!userFundList || !Array.isArray(userFundList)) return 0;
for (let i = 0, len = userFundList.length; i < len; ++i) {
const fund = userFundList[i]; // 一条数据库fund表记录
// if (fund.lastMine && new Date(fund.lastMine).getDate() === new Date().getDate()) {
// mylog.info('已经计算过...跳过');
// continue;
// }
const user = await User.findById(fund.userId).exec();
console.log('No. ', currentIndex, ' - ', i);
mylog.info('开始更新用户: ', user.id);
await doReward(user, fund);
mylog.info('用户: ', user.id, '更新完毕\n');
typeof job.touch === 'function' && job.touch();
await system.updateOne({ key: 'userIndex4job' }, {
$set: {
value: currentIndex
}
});
await system.updateOne({ key: 'restFundNum' }, {
$inc: {
value: -1
}
});
}
currentIndex += 10;
}
mylog.info('收益计算分配完成');
await system.findOneAndUpdate({
key: 'userIndex4job'
}, { $set: { value: 0 } }).exec();
await system.findOneAndUpdate({
key: 'mineCount',
}, {
$inc: {
value: 1
}
}, { upsert: true });
await system.findOneAndUpdate({
key: 'lastMine',
}, {
value: new Date().toISOString()
}, { upsert: true });
typeof done === 'function' && done('收益计算分配完成');
process.exit();
}
const start = async () => {
const SysConfig = require('./configSec');
mongoose.set('useCreateIndex', true);
const { DB_USER_NAME, DB_PASSWD, DB_HOST, DB_PORT, DB_NAME } = SysConfig;
const db = mongoose.connection;
db.on('error', mylog.error);
db.once('open', function() {
mylog.info('数据库连接成功...');
});
mylog.info('开始连接数据库...');
await mongoose.connect(`mongodb://${DB_USER_NAME}:${DB_PASSWD}@${DB_HOST}:${DB_PORT}/${DB_NAME}`, {
useNewUrlParser: true,
bufferMaxEntries: 0,
autoReconnect: true,
useFindAndModify: false,
useUnifiedTopology: true
});
mine();
};
start();