3 var env = require('gitter-web-env');
4 var errorReporter = env.errorReporter;
5 var winston = env.logger;
6 var nconf = env.config;
7 var pushNotificationFilter = require('gitter-web-push-notification-filter');
8 var workerQueue = require('gitter-web-utils/lib/worker-queue-redis');
9 var debug = require('debug')('gitter:app:push-notification-postbox');
10 var mongoUtils = require('gitter-web-persistence-utils/lib/mongo-utils');
11 var Promise = require('bluebird');
13 var notificationWindowPeriods = [
14 nconf.get('notifications:notificationDelay') * 1000,
15 nconf.get('notifications:notificationDelay2') * 1000
18 /* 10 second window for users on mention */
19 var mentionNotificationWindowPeriod = 10000;
20 var maxNotificationsForMentions = 10;
21 var maxNotificationsForNonMentions = notificationWindowPeriods.length;
23 // This queue is responsible to taking notifications and deciding which users to forward them on to
24 var pushNotificationFilterQueue = workerQueue.queue('push-notifications-filter', {}, function() {
25 return function(data, done) {
26 var troupeId = data.troupeId;
27 var chatId = data.chatId;
28 var userIds = data.userIds;
29 var mentioned = data.mentioned;
31 return filterNotificationsForPush(troupeId, chatId, userIds, mentioned)
33 debug('filterNotificationsForPush complete');
35 .catch(function(err) {
36 winston.error('Unable to queue notification: ' + err, { exception: err });
42 // This queue is responsible to generating the actual content of the push notification and sending it to users
43 var pushNotificationGeneratorQueue = workerQueue.queue(
44 'push-notifications-generate',
47 var pushNotificationGenerator = require('./push-notification-generator');
49 return function(data, done) {
50 var userId = data.userId;
51 var troupeId = data.troupeId;
52 var notificationNumber = data.notificationNumber;
54 debug('Spooling push notification for %s in %s, #%s', userId, troupeId, notificationNumber);
56 if (!userId || !troupeId || !notificationNumber) return done();
58 return pushNotificationGenerator
59 .sendUserTroupeNotification(userId, troupeId, notificationNumber)
60 .catch(function(err) {
61 winston.error('Failed to send notifications: ' + err + '. Failing silently.', {
66 { userId: userId, troupeId: troupeId },
67 { module: 'push-notification-postbox' }
75 function filterNotificationsForPush(troupeId, chatId, userIds, mentioned) {
76 var chatTime = mongoUtils.getTimestampFromObjectId(chatId);
77 debug('filterNotificationsForPush for %s users', userIds.length);
79 return Promise.map(userIds, function(userId) {
80 var maxLocks = mentioned ? maxNotificationsForMentions : maxNotificationsForNonMentions;
82 // TODO: bulk version of this method please
83 return pushNotificationFilter
84 .canLockForNotification(userId, troupeId, chatTime, maxLocks)
85 .then(function(notificationNumber) {
86 if (!notificationNumber) {
87 // TODO: For mentions: consider cancelling the current lock on mentions and creating a
88 // new one as if we're in the 60 second window period, we'll need to
89 // wait until the end of the window before sending the mention
91 'Unable to obtain a lock (max=%s) for user %s in troupe %s. Will not notify',
101 /* Send the notification to the user very shortly */
102 delay = mentionNotificationWindowPeriod;
104 delay = notificationWindowPeriods[notificationNumber - 1];
106 debug('Obtained a lock in excess of the maximum lock number of %s', maxLocks);
112 'Queuing notification %s to be send to user %s in %sms',
118 return pushNotificationGeneratorQueue.invoke(
122 notificationNumber: notificationNumber
130 exports.queueNotificationsForChat = function(troupeId, chatId, userIds, mentioned) {
131 debug('queueNotificationsForChat for %s users', userIds.length);
133 return pushNotificationFilterQueue.invoke({
141 exports.listen = function() {
142 pushNotificationGeneratorQueue.listen();
143 pushNotificationFilterQueue.listen();