Created
October 5, 2016 15:57
-
-
Save crrobinson14/b93431c5f2a3a337693ffa5d2f9e9eb5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var pendingNotifications = {}, | |
publicApi = {}, | |
api; | |
// Dummy function to avoid an Unhandled Rejection error if the user is offline. Prevents us | |
// from needing to .catch() the notification result in every spot where we call it. Also a | |
// useful debugging point, so we don't just null it out. | |
function userNotOnline() { | |
} | |
/** | |
* Send a message to a specific user by their user ID. Optionally falls back to push notifications | |
* if the user is not online in the cluster. | |
* @param {Number} userId The ID of the user to reach | |
* @param {String} room The room to send the message to, typically 'system' | |
* @param {*} message The message to send. | |
* @ | |
*/ | |
publicApi.notifyUser = function(userId, room, message) { | |
var notificationId = Math.uuid(12); | |
api.log('NOTIFICATIONS: Notifying user {0} with message'.format(userId), 'info', message); | |
// Yes, yes, we know this pattern is deprecated | |
return new api.Promise(function(resolve) { | |
pendingNotifications[notificationId] = { | |
posted: Date.now(), | |
userId: userId, | |
room: room, | |
message: message, | |
resolve: resolve, | |
reject: userNotOnline | |
}; | |
api.redis.doCluster('api.notifications.handleNotifyUser', [notificationId, userId, room, message]); | |
}); | |
}; | |
// @private, should only be called via notifyUser. | |
publicApi.handleNotifyUser = function(notificationId, userId, room, message) { | |
Object.keys(api.connections.connections).map(function(connectionId) { | |
var connection = api.connections.connections[connectionId]; | |
if (connection.session && connection.session.userId === userId && connection.type === 'websocket') { | |
api.log('NOTIFICATIONS: [{0}] has user {1} for {2}'.format(api.uniqueWorkerId, userId, notificationId), 'info', message); | |
connection.sendMessage({ context: 'user', room: room, message: message }); | |
api.redis.doCluster('api.notifications.handleNotificationSent', [notificationId]); | |
} | |
}); | |
}; | |
// @private, should only be called via notifyUser. | |
publicApi.handleNotificationSent = function(notificationId) { | |
var pending = pendingNotifications[notificationId]; | |
if (pending) { | |
pending.resolve(notificationId); | |
delete pendingNotifications[notificationId]; | |
} | |
}; | |
/** | |
* Send an array of messages to a specific user | |
* @param {Object} connection The user to send to | |
* @param {String} room The name of the room to which the messages should be sent | |
* @param {Array} messages The array of messages to transmit | |
*/ | |
publicApi.sendMessagesToConnection = function(connection, room, messages) { | |
(messages || []).map(function(message) { | |
connection.sendMessage({ | |
context: 'user', | |
room: room, | |
message: message | |
}); | |
}); | |
}; | |
module.exports = { | |
initialize: function(_api, next) { | |
api = _api; | |
api.notifications = publicApi; | |
next(); | |
}, | |
start: function(_api, next) { | |
var notificationTimeoutCheck = setInterval(function() { | |
var now = Date.now(); | |
Object.keys(pendingNotifications).map(function(notificationId) { | |
var notification = pendingNotifications[notificationId]; | |
if (notification.posted + 5000 < now) { | |
notification.reject(api.responses.notFoundError()); | |
delete pendingNotifications[notificationId]; | |
} | |
}); | |
}, 5000); | |
notificationTimeoutCheck.unref(); | |
next(); | |
}, | |
stop: function(_api, next) { | |
next(); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment