mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Fixes asynchronous cron bug that allows cron to run twice for a user within seconds. (#10142)
* Fixes asynchronous cron bug that allows cron to run twice for a user within seconds of eachother. fixes #8991 * Fixing tests. * Updating assignment to keep user and res.locals.user in sync.
This commit is contained in:
@@ -166,11 +166,14 @@ describe('cron middleware', () => {
|
||||
await new Promise((resolve, reject) => {
|
||||
cronMiddleware(req, res, (err) => {
|
||||
if (err) return reject(err);
|
||||
expect(user.stats.hp).to.be.lessThan(hpBefore);
|
||||
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
|
||||
if (secondErr) return reject(secondErr);
|
||||
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('updates tasks', async () => {
|
||||
user.lastCron = moment(new Date()).subtract({days: 2});
|
||||
@@ -217,11 +220,14 @@ describe('cron middleware', () => {
|
||||
await new Promise((resolve, reject) => {
|
||||
cronMiddleware(req, res, (err) => {
|
||||
if (err) return reject(err);
|
||||
expect(user.stats.hp).to.be.lessThan(hpBefore);
|
||||
User.findOne({_id: user._id}, function (secondErr, updatedUser) {
|
||||
if (secondErr) return reject(secondErr);
|
||||
expect(updatedUser.stats.hp).to.be.lessThan(hpBefore);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('recovers from failed cron and does not error when user is already cronning', async () => {
|
||||
user.lastCron = moment(new Date()).subtract({days: 2});
|
||||
|
||||
@@ -23,7 +23,6 @@ async function checkForActiveCron (user, now) {
|
||||
}, {
|
||||
$set: {
|
||||
_cronSignature,
|
||||
lastCron: now, // setting lastCron now so we don't risk re-running parts of cron if it fails
|
||||
'auth.timestamps.loggedin': now,
|
||||
},
|
||||
}).exec();
|
||||
@@ -35,6 +34,14 @@ async function checkForActiveCron (user, now) {
|
||||
}
|
||||
}
|
||||
|
||||
async function updateLastCron (user, now) {
|
||||
await User.update({
|
||||
_id: user._id,
|
||||
}, {
|
||||
lastCron: now, // setting lastCron now so we don't risk re-running parts of cron if it fails
|
||||
}).exec();
|
||||
}
|
||||
|
||||
async function unlockUser (user) {
|
||||
await User.update({
|
||||
_id: user._id,
|
||||
@@ -51,9 +58,12 @@ async function cronAsync (req, res) {
|
||||
let now = new Date();
|
||||
|
||||
try {
|
||||
await checkForActiveCron(user, now);
|
||||
|
||||
user = res.locals.user = await User.findOne({_id: user._id}).exec();
|
||||
let {daysMissed, timezoneOffsetFromUserPrefs} = user.daysUserHasMissed(now, req);
|
||||
|
||||
await checkForActiveCron(user, now);
|
||||
await updateLastCron(user, now);
|
||||
|
||||
if (daysMissed <= 0) {
|
||||
if (user.isModified()) await user.save();
|
||||
|
||||
Reference in New Issue
Block a user