Tasks cron ryamodal fixes (#8871)

* Changed assumption of timezone location

* Added checks for RYA and moved cron check

* Fixed modal scope issue
This commit is contained in:
Keith Holliday 2017-07-13 16:11:27 -06:00 committed by Sabe Jones
parent 4cd272f99c
commit bc477455bb
4 changed files with 41 additions and 25 deletions

View file

@ -1,8 +1,8 @@
'use strict'; 'use strict';
habitrpg.controller('NotificationCtrl', habitrpg.controller('NotificationCtrl',
['$scope', '$rootScope', 'Shared', 'Content', 'User', 'Guide', 'Notification', 'Analytics', 'Achievement', 'Social', 'Tasks', ['$scope', '$rootScope', 'Shared', 'Content', 'User', 'Guide', 'Notification', 'Analytics', 'Achievement', 'Social', 'Tasks', '$modal',
function ($scope, $rootScope, Shared, Content, User, Guide, Notification, Analytics, Achievement, Social, Tasks) { function ($scope, $rootScope, Shared, Content, User, Guide, Notification, Analytics, Achievement, Social, Tasks, $modal) {
var isRunningYesterdailies = false; var isRunningYesterdailies = false;
$rootScope.$watch('user', function (after, before) { $rootScope.$watch('user', function (after, before) {
@ -53,7 +53,8 @@ habitrpg.controller('NotificationCtrl',
modalScope.processingYesterdailies = true; modalScope.processingYesterdailies = true;
$scope.yesterDailiesModalOpen = true; $scope.yesterDailiesModalOpen = true;
$rootScope.openModal('yesterDailies', { $modal.open({
templateUrl: 'modals/yesterDailies.html',
scope: modalScope, scope: modalScope,
backdrop: 'static', backdrop: 'static',
controller: ['$scope', 'Tasks', 'User', '$rootScope', function ($scope, Tasks, User, $rootScope) { controller: ['$scope', 'Tasks', 'User', '$rootScope', function ($scope, Tasks, User, $rootScope) {

View file

@ -423,7 +423,7 @@ angular.module('habitrpg')
url: 'api/v3/cron', url: 'api/v3/cron',
}) })
.then(function (response) { .then(function (response) {
sync(); return sync();
}) })
}, },

View file

@ -30,12 +30,14 @@ export function setNextDue (task, user, dueDateOption) {
let dateTaskIsDue = Date.now(); let dateTaskIsDue = Date.now();
if (dueDateOption) { if (dueDateOption) {
// @TODO Add required ISO format // @TODO Add required ISO format
dateTaskIsDue = moment(dueDateOption).add(user.preferences.timezoneOffset, 'minutes'); dateTaskIsDue = moment(dueDateOption);
// If not time is supplied. Let's assume we want start of Custom Day Start day. // If not time is supplied. Let's assume we want start of Custom Day Start day.
if (dateTaskIsDue.hour() === 0 && dateTaskIsDue.minute() === 0 && dateTaskIsDue.second() === 0 && dateTaskIsDue.millisecond() === 0) { if (dateTaskIsDue.hour() === 0 && dateTaskIsDue.minute() === 0 && dateTaskIsDue.second() === 0 && dateTaskIsDue.millisecond() === 0) {
dateTaskIsDue.add(user.preferences.timezoneOffset, 'minutes');
dateTaskIsDue.add(user.preferences.dayStart, 'hours'); dateTaskIsDue.add(user.preferences.dayStart, 'hours');
} }
now = dateTaskIsDue; now = dateTaskIsDue;
} }

View file

@ -7,6 +7,36 @@ import { recoverCron, cron } from '../libs/cron';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import logger from '../libs/logger'; import logger from '../libs/logger';
async function checkForActiveCron (user, now) {
let _cronSignature = uuid();
// To avoid double cron we first set _cronSignature and then check that it's not changed while processing
let userUpdateResult = await User.update({
_id: user._id,
_cronSignature: 'NOT_RUNNING', // Check that in the meantime another cron has not started
}, {
$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();
// If the cron signature is already set, cron is running in another request
// throw an error and recover later,
if (userUpdateResult.nMatched === 0 || userUpdateResult.nModified === 0) {
throw new Error('CRON_ALREADY_RUNNING');
}
}
async function unlockUser (user) {
await User.update({
_id: user._id,
}, {
_cronSignature: 'NOT_RUNNING',
}).exec();
}
async function cronAsync (req, res) { async function cronAsync (req, res) {
let user = res.locals.user; let user = res.locals.user;
if (!user) return null; // User might not be available when authentication is not mandatory if (!user) return null; // User might not be available when authentication is not mandatory
@ -17,31 +47,14 @@ async function cronAsync (req, res) {
try { try {
let {daysMissed, timezoneOffsetFromUserPrefs} = user.daysUserHasMissed(now, req); let {daysMissed, timezoneOffsetFromUserPrefs} = user.daysUserHasMissed(now, req);
await checkForActiveCron(user, now);
if (daysMissed <= 0) { if (daysMissed <= 0) {
if (user.isModified()) await user.save(); if (user.isModified()) await user.save();
await unlockUser(user);
return null; return null;
} }
let _cronSignature = uuid();
// To avoid double cron we first set _cronSignature and then check that it's not changed while processing
let userUpdateResult = await User.update({
_id: user._id,
_cronSignature: 'NOT_RUNNING', // Check that in the meantime another cron has not started
}, {
$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();
// If the cron signature is already set, cron is running in another request
// throw an error and recover later,
if (userUpdateResult.nMatched === 0 || userUpdateResult.nModified === 0) {
throw new Error('CRON_ALREADY_RUNNING');
}
let tasks = await Tasks.Task.find({ let tasks = await Tasks.Task.find({
userId: user._id, userId: user._id,
$or: [ // Exclude completed todos $or: [ // Exclude completed todos