matchmaker-redis
Version:
A module that helps users join some kind of social event such as a multiplayer game.
104 lines (86 loc) • 3.04 kB
JavaScript
const _ = require('lodash')
const shortid = require('shortid')
const installLuaScripts = require('./lib/lua-scipts')
const pendingKey = 'events/pending'
const activeKey = 'events/active'
var redis
function createEvent(args) {
const userId = args.userId
const userAlias = args.userAlias
if (_.isUndefined(userId) || _.isUndefined(userAlias))
return Promise.reject(new Error('user required'))
const capacity = Math.max(2, parseInt(args.capacity, 10) || 0)
const whitelist = _.uniq(args.whitelist || [])
const blacklist = _.uniq(args.blacklist || [])
if (_.indexOf(whitelist, userId) !== -1 ||
_.indexOf(blacklist, userId) !== -1 ||
!_.isEmpty(_.intersection(whitelist, blacklist)))
return Promise.reject(new Error('invalid whitelist/blacklist'))
const perUserTimeoutSec = Math.max(1, parseInt(args.perUserTimeoutSec, 10) || 30)
const params = args.params || ''
if (!_.isString(params))
return Promise.reject(new Error('invalid params'))
const event = {
id: shortid(),
capacity,
params: _.trim(params),
whitelist,
blacklist,
userIds: [userId],
aliases: [userAlias]
}
return redis.createEvent(`events/${event.id}`, pendingKey, JSON.stringify(event)).then(() => {
const timeout = event.capacity * perUserTimeoutSec * 1000
setTimeout(function autoCancelEvent() {
cancelEvent(userId, event.id).catch(err => {
// Just eat this error since it's an automatic cancellation or expiration;
// not a user action.
//
// console.warn('cannot auto-cancel event %s: %s', event.id, err.message)
})
}, timeout)
return event
})
}
function autojoinEvent(args) {
const userId = args.userId
const userAlias = args.userAlias
if (_.isUndefined(userId) || _.isUndefined(userAlias))
return Promise.reject(new Error('user required'))
const capacity = Math.max(2, parseInt(args.capacity, 10) || 0)
const params = args.params || ''
if (!_.isString(params))
return Promise.reject(new Error('invalid params'))
return redis.autojoinEvent(
pendingKey,
activeKey,
userId,
userAlias,
capacity,
params,
_.now() / 1000 | 0)
.then(json => !json ? null : JSON.parse(json))
}
function cancelEvent(userId, eventId) {
return redis.cancelEvent(`events/${eventId}`, pendingKey, userId)
}
function getEventsFor(userId) {
return redis.getPendingEventsFor(pendingKey, userId).then(function (json) {
this.pendingEvents = JSON.parse(json)
return redis.getActiveEventsFor(activeKey, userId)
}).then(function (json) {
return {
pending: this.pendingEvents,
active: JSON.parse(json)
}
})
}
function joinEvent(userId, userAlias, eventId) {
return redis.joinEvent(`events/${eventId}`, pendingKey, activeKey,
userId, userAlias, _.now() / 1000 | 0).then(JSON.parse)
}
module.exports = function (redisClient) {
redis = redisClient
installLuaScripts(redisClient)
return {createEvent, autojoinEvent, getEventsFor, joinEvent, cancelEvent}
}