From b110aec6ed73582bcaabce3f12479b6aaa3064a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Sun, 15 Sep 2019 22:41:25 -0400 Subject: [PATCH] refactor: async/await rewards --- src/rewards/admin.js | 171 ++++++++++++++----------------------------- src/rewards/index.js | 161 +++++++++++++++------------------------- 2 files changed, 112 insertions(+), 220 deletions(-) diff --git a/src/rewards/admin.js b/src/rewards/admin.js index b7d0d7a235..63f36a98b2 100644 --- a/src/rewards/admin.js +++ b/src/rewards/admin.js @@ -1,143 +1,80 @@ 'use strict'; -var async = require('async'); -var plugins = require('../plugins'); -var db = require('../database'); +const plugins = require('../plugins'); +const db = require('../database'); +const utils = require('../utils'); -var rewards = module.exports; +const rewards = module.exports; -rewards.save = function (data, callback) { - async.each(data, function save(data, next) { +rewards.save = async function (data) { + async function save(data) { if (!Object.keys(data.rewards).length) { - return next(); + return; } - - var rewardsData = data.rewards; + const rewardsData = data.rewards; delete data.rewards; - - async.waterfall([ - function (next) { - if (!parseInt(data.id, 10)) { - db.incrObjectField('global', 'rewards:id', next); - } else { - next(null, data.id); - } - }, - function (rid, next) { - data.id = rid; - - async.series([ - function (next) { - rewards.delete(data, next); - }, - function (next) { - db.setAdd('rewards:list', data.id, next); - }, - function (next) { - db.setObject('rewards:id:' + data.id, data, next); - }, - function (next) { - db.setObject('rewards:id:' + data.id + ':rewards', rewardsData, next); - }, - ], next); - }, - ], next); - }, function (err) { - if (err) { - return callback(err); + if (!parseInt(data.id, 10)) { + data.id = await db.incrObjectField('global', 'rewards:id'); } + await rewards.delete(data); + await db.setAdd('rewards:list', data.id); + await db.setObject('rewards:id:' + data.id, data); + await db.setObject('rewards:id:' + data.id + ':rewards', rewardsData); + } - saveConditions(data, callback); - }); + await Promise.all(data.map(data => save(data))); + await saveConditions(data); }; -rewards.delete = function (data, callback) { - async.parallel([ - function (next) { - db.setRemove('rewards:list', data.id, next); - }, - function (next) { - db.delete('rewards:id:' + data.id, next); - }, - function (next) { - db.delete('rewards:id:' + data.id + ':rewards', next); - }, - ], callback); +rewards.delete = async function (data) { + await Promise.all([ + db.setRemove('rewards:list', data.id), + db.delete('rewards:id:' + data.id), + db.delete('rewards:id:' + data.id + ':rewards'), + ]); }; -rewards.get = function (callback) { - async.parallel({ +rewards.get = async function () { + return await utils.promiseParallel({ active: getActiveRewards, - conditions: function (next) { - plugins.fireHook('filter:rewards.conditions', [], next); - }, - conditionals: function (next) { - plugins.fireHook('filter:rewards.conditionals', [], next); - }, - rewards: function (next) { - plugins.fireHook('filter:rewards.rewards', [], next); - }, - }, callback); + conditions: plugins.fireHook('filter:rewards.conditions', []), + conditionals: plugins.fireHook('filter:rewards.conditionals', []), + rewards: plugins.fireHook('filter:rewards.rewards', []), + }); }; -function saveConditions(data, callback) { - var rewardsPerCondition = {}; - async.waterfall([ - function (next) { - db.delete('conditions:active', next); - }, - function (next) { - var conditions = []; - - data.forEach(function (reward) { - conditions.push(reward.condition); - rewardsPerCondition[reward.condition] = rewardsPerCondition[reward.condition] || []; - rewardsPerCondition[reward.condition].push(reward.id); - }); +async function saveConditions(data) { + const rewardsPerCondition = {}; + await db.delete('conditions:active'); + const conditions = []; - db.setAdd('conditions:active', conditions, next); - }, - function (next) { - async.each(Object.keys(rewardsPerCondition), function (condition, next) { - db.setAdd('condition:' + condition + ':rewards', rewardsPerCondition[condition], next); - }, next); - }, - ], function (err) { - callback(err); + data.forEach(function (reward) { + conditions.push(reward.condition); + rewardsPerCondition[reward.condition] = rewardsPerCondition[reward.condition] || []; + rewardsPerCondition[reward.condition].push(reward.id); }); -} - -function getActiveRewards(callback) { - var activeRewards = []; - function load(id, next) { - async.parallel({ - main: function (next) { - db.getObject('rewards:id:' + id, next); - }, - rewards: function (next) { - db.getObject('rewards:id:' + id + ':rewards', next); - }, - }, function (err, data) { - if (data.main) { - data.main.disabled = data.main.disabled === 'true'; - data.main.rewards = data.rewards; - activeRewards.push(data.main); - } + await db.setAdd('conditions:active', conditions); - next(err); - }); - } + await Promise.all(Object.keys(rewardsPerCondition).map(c => db.setAdd('condition:' + c + ':rewards', rewardsPerCondition[c]))); +} - db.getSetMembers('rewards:list', function (err, rewards) { - if (err) { - return callback(err); +async function getActiveRewards() { + async function load(id) { + const [main, rewards] = await Promise.all([ + db.getObject('rewards:id:' + id), + db.getObject('rewards:id:' + id + ':rewards'), + ]); + if (main) { + main.disabled = main.disabled === 'true'; + main.rewards = rewards; } + return main; + } - async.eachSeries(rewards, load, function (err) { - callback(err, activeRewards); - }); - }); + const rewardsList = await db.getSetMembers('rewards:list'); + const rewardData = await Promise.all(rewardsList.map(id => load(id))); + return rewardData.filter(Boolean); } require('../promisify')(rewards); diff --git a/src/rewards/index.js b/src/rewards/index.js index ca75df9ca1..3ccdfee701 100644 --- a/src/rewards/index.js +++ b/src/rewards/index.js @@ -1,123 +1,78 @@ 'use strict'; - -var async = require('async'); -var db = require('../database'); -var plugins = require('../plugins'); - -var rewards = module.exports; - -rewards.checkConditionAndRewardUser = function (uid, condition, method, callback) { - callback = callback || function () {}; - - async.waterfall([ - function (next) { - isConditionActive(condition, next); - }, - function (isActive, next) { - if (!isActive) { - return callback(); - } - getIDsByCondition(condition, next); - }, - function (ids, next) { - getRewardDataByIDs(ids, next); - }, - function (rewards, next) { - filterCompletedRewards(uid, rewards, next); - }, - function (rewards, next) { - if (!rewards || !rewards.length) { - return callback(); - } - - async.filter(rewards, function (reward, next) { - if (!reward) { - return next(null, false); - } - - checkCondition(reward, method, next); - }, function (err, eligible) { - if (err || !eligible) { - return next(false); - } - - giveRewards(uid, eligible, next); - }); - }, - ], callback); +const util = require('util'); + +const db = require('../database'); +const plugins = require('../plugins'); + +const rewards = module.exports; + +rewards.checkConditionAndRewardUser = async function (uid, condition, method) { + const isActive = await isConditionActive(condition); + if (!isActive) { + return; + } + const ids = await getIDsByCondition(condition); + let rewardData = await getRewardDataByIDs(ids); + rewardData = await filterCompletedRewards(uid, rewardData); + rewardData = rewardData.filter(Boolean); + if (!rewardData || !rewardData.length) { + return; + } + const eligible = await Promise.all(rewardData.map(reward => checkCondition(reward, method))); + const eligibleRewards = rewardData.filter((reward, index) => eligible[index]); + await giveRewards(uid, eligibleRewards); }; -function isConditionActive(condition, callback) { - db.isSetMember('conditions:active', condition, callback); +async function isConditionActive(condition) { + return await db.isSetMember('conditions:active', condition); } -function getIDsByCondition(condition, callback) { - db.getSetMembers('condition:' + condition + ':rewards', callback); +async function getIDsByCondition(condition) { + return await db.getSetMembers('condition:' + condition + ':rewards'); } -function filterCompletedRewards(uid, rewards, callback) { - async.waterfall([ - function (next) { - db.getSortedSetRangeByScoreWithScores('uid:' + uid + ':rewards', 0, -1, 1, '+inf', next); - }, - function (data, next) { - var userRewards = {}; +async function filterCompletedRewards(uid, rewards) { + const data = await db.getSortedSetRangeByScoreWithScores('uid:' + uid + ':rewards', 0, -1, 1, '+inf'); + const userRewards = {}; - data.forEach(function (obj) { - userRewards[obj.value] = parseInt(obj.score, 10); - }); + data.forEach(function (obj) { + userRewards[obj.value] = parseInt(obj.score, 10); + }); - rewards = rewards.filter(function (reward) { - if (!reward) { - return false; - } + return rewards.filter(function (reward) { + if (!reward) { + return false; + } - var claimable = parseInt(reward.claimable, 10); - return claimable === 0 || (!userRewards[reward.id] || userRewards[reward.id] < reward.claimable); - }); - - next(null, rewards); - }, - ], callback); + const claimable = parseInt(reward.claimable, 10); + return claimable === 0 || (!userRewards[reward.id] || userRewards[reward.id] < reward.claimable); + }); } -function getRewardDataByIDs(ids, callback) { - db.getObjects(ids.map(function (id) { - return 'rewards:id:' + id; - }), callback); +async function getRewardDataByIDs(ids) { + return await db.getObjects(ids.map(id => 'rewards:id:' + id)); } -function getRewardsByRewardData(rewards, callback) { - db.getObjects(rewards.map(function (reward) { - return 'rewards:id:' + reward.id + ':rewards'; - }), callback); +async function getRewardsByRewardData(rewards) { + return await db.getObjects(rewards.map(reward => 'rewards:id:' + reward.id + ':rewards')); } -function checkCondition(reward, method, callback) { - async.waterfall([ - function (next) { - method(next); - }, - function (value, next) { - plugins.fireHook('filter:rewards.checkConditional:' + reward.conditional, { left: value, right: reward.value }, next); - }, - function (bool, next) { - next(null, bool); - }, - ], callback); +async function checkCondition(reward, method) { + if (method.constructor && method.constructor.name !== 'AsyncFunction') { + method = util.promisify(method); + } + const value = await method(); + const bool = await plugins.fireHook('filter:rewards.checkConditional:' + reward.conditional, { left: value, right: reward.value }); + return bool; } -function giveRewards(uid, rewards, callback) { - async.waterfall([ - function (next) { - getRewardsByRewardData(rewards, next); - }, - function (rewardData, next) { - async.each(rewards, function (reward, next) { - plugins.fireHook('action:rewards.award:' + reward.rid, { uid: uid, reward: rewardData[rewards.indexOf(reward)] }); - db.sortedSetIncrBy('uid:' + uid + ':rewards', 1, reward.id, next); - }, next); - }, - ], callback); +async function giveRewards(uid, rewards) { + const rewardData = await getRewardsByRewardData(rewards); + await Promise.all(rewards.map(async function (reward) { + plugins.fireHook('action:rewards.award:' + reward.rid, { uid: uid, reward: rewardData[rewards.indexOf(reward)] }); + await db.sortedSetIncrBy('uid:' + uid + ':rewards', 1, reward.id); + })); } + +require('../promisify')(rewards);