Webhooks: store meeting ID mappings in a global model

This commit is contained in:
Leonardo Crauss Daronco 2014-11-12 13:07:54 -02:00
parent fd90a46563
commit bfdae8f204
5 changed files with 48 additions and 27 deletions

View File

@ -42,7 +42,7 @@ module.exports = class CallbackEmitter extends EventEmitter
request requestOptions, (error, response, body) -> request requestOptions, (error, response, body) ->
if error? if error?
console.log "Error calling url:",requestOptions.uri console.log "X=> Error in the callback call to: [#{requestOptions.uri}] for #{simplifiedEvent(data.event)}"
console.log "Error:", error console.log "Error:", error
console.log "Response:", response console.log "Response:", response
callback error, false callback error, false

View File

@ -1,6 +1,7 @@
_ = require("lodash") _ = require("lodash")
CallbackEmitter = require("./callback_emitter") CallbackEmitter = require("./callback_emitter")
MeetingIDMap = require("./meeting_id_map")
# The database of hooks. # The database of hooks.
db = {} db = {}
@ -76,7 +77,7 @@ module.exports = class Hook
if hook? if hook?
callback?(new Error("There is already a subscription for this callback URL"), hook) callback?(new Error("There is already a subscription for this callback URL"), hook)
else else
msg = "Hook: adding a subscription with callback URL [#{callbackURL}]" msg = "Hook: adding a hook with callback URL [#{callbackURL}]"
msg += " for the meeting [#{meetingID}]" if meetingID? msg += " for the meeting [#{meetingID}]" if meetingID?
console.log msg console.log msg
@ -85,6 +86,7 @@ module.exports = class Hook
hook.callbackURL = callbackURL hook.callbackURL = callbackURL
hook.externalMeetingID = meetingID hook.externalMeetingID = meetingID
hook.saveSync() hook.saveSync()
callback?(null, hook) callback?(null, hook)
@removeSubscription = (hookID, callback) -> @removeSubscription = (hookID, callback) ->
@ -112,11 +114,10 @@ module.exports = class Hook
else else
null null
@allForMeetingSync = (externalMeetingID) -> @findByExternalMeetingIDSync = (externalMeetingID) ->
hooks = Hook.allSync() hooks = Hook.allSync()
_.filter(hooks, (hook) -> _.filter(hooks, (hook) ->
hook.isGlobal() or (externalMeetingID? and externalMeetingID is hook.externalMeetingID)
(externalMeetingID? and externalMeetingID is hook.targetMeetingID())
) )
@allGlobalSync = -> @allGlobalSync = ->

View File

@ -0,0 +1,28 @@
_ = require("lodash")
# The database of mappings. Format:
# { internalMeetingID: externalMeetingID }
db = {}
# A simple model to store mappings for meeting IDs.
module.exports = class MeetingIDMap
@addMapping = (internalMeetingID, externalMeetingID) ->
unless internalMeetingID in _.keys(db)
db[internalMeetingID] = externalMeetingID
console.log "MeetingIDMap: added meeting mapping to the list { #{internalMeetingID}: #{db[internalMeetingID]} }"
@removeMapping = (internalMeetingID) ->
if internalMeetingID in _.keys(db)
console.log "MeetingIDMap: removing meeting mapping from the list { #{internalMeetingID}: #{db[internalMeetingID]} }"
delete db[internalMeetingID]
db[internalMeetingID] = null
@getInternalMeetingID = (externalMeetingID) ->
for internal, external of db
if external is externalMeetingID
return internal
null
@getExternalMeetingID = (internalMeetingID) ->
db[internalMeetingID]

View File

@ -5,6 +5,7 @@ request = require("request")
config = require("./config") config = require("./config")
Hook = require("./hook") Hook = require("./hook")
MeetingIDMap = require("./meeting_id_map")
# Web hooks will listen for events on redis coming from BigBlueButton and # Web hooks will listen for events on redis coming from BigBlueButton and
# perform HTTP calls with them to all registered hooks. # perform HTTP calls with them to all registered hooks.
@ -15,7 +16,6 @@ module.exports = class WebHooks
@client = redis.createClient() @client = redis.createClient()
# To map internal and external meeting IDs # To map internal and external meeting IDs
@meetingMappings = {}
@subscriberMeetings = redis.createClient() @subscriberMeetings = redis.createClient()
start: -> start: ->
@ -51,16 +51,14 @@ module.exports = class WebHooks
# Processes an event received from redis. Will get all hook URLs that # Processes an event received from redis. Will get all hook URLs that
# should receive this event and start the process to perform the callback. # should receive this event and start the process to perform the callback.
_processEvent: (message) -> _processEvent: (message) ->
hooks = Hook.allSync(message) hooks = Hook.allGlobalSync()
# filter the hooks that need to receive this event # filter the hooks that need to receive this event
# only global hooks or hooks for this specific meeting # only global hooks or hooks for this specific meeting
idFromMessage = message.payload?.meeting_id # always the internal meetingID idFromMessage = message.payload?.meeting_id
if idFromMessage? if idFromMessage?
externalMeetingID = @meetingMappings[idFromMessage] eMeetingID = MeetingIDMap.getExternalMeetingID(idFromMessage)
hooks = Hook.allForMeetingSync(externalMeetingID) hooks = hooks.concat(Hook.findByExternalMeetingIDSync(eMeetingID))
else
hooks = Hook.allGlobalSync(externalMeetingID)
hooks.forEach (hook) -> hooks.forEach (hook) ->
console.log "WebHooks: enqueueing a message in the hook:", hook.callbackURL console.log "WebHooks: enqueueing a message in the hook:", hook.callbackURL
@ -77,26 +75,15 @@ module.exports = class WebHooks
try try
message = JSON.parse(message) message = JSON.parse(message)
if message.header?.name is "meeting_created_message" if message.header?.name is "meeting_created_message"
@_addMeetingMapping(message.payload?.meeting_id, message.payload?.external_meeting_id) MeetingIDMap.addMapping(message.payload?.meeting_id, message.payload?.external_meeting_id)
else if message.header?.name is "meeting_destroyed_event" else if message.header?.name is "meeting_destroyed_event"
@_removeMeetingMapping(message.payload?.meeting_id) MeetingIDMap.removeMapping(message.payload?.meeting_id)
catch e catch e
console.log "WebHooks: error processing the message", JSON.stringify(message), ":", e console.log "WebHooks: error processing the message", JSON.stringify(message), ":", e
@subscriberMeetings.subscribe config.hooks.meetingsChannel @subscriberMeetings.subscribe config.hooks.meetingsChannel
_addMeetingMapping: (meetingID, externalMeetingID) ->
unless meetingID in _.keys(@meetingMappings)
@meetingMappings[meetingID] = externalMeetingID
console.log "WebHooks: added meeting mapping to the list { #{meetingID}: #{@meetingMappings[meetingID]} }"
_removeMeetingMapping: (meetingID) ->
if meetingID in _.keys(@meetingMappings)
console.log "WebHooks: removing meeting mapping from the list { #{meetingID}: #{@meetingMappings[meetingID]} }"
delete @meetingMappings[meetingID]
@meetingMappings[meetingID] = null
# TODO: enable the methods below again when we persist hooks to redis again # TODO: enable the methods below again when we persist hooks to redis again
# # Gets all hooks from redis. # # Gets all hooks from redis.
# # Calls `callback(errors, result)` when done. `result` is an array of `Hook` objects. # # Calls `callback(errors, result)` when done. `result` is an array of `Hook` objects.

View File

@ -1,3 +1,4 @@
_ = require("lodash")
express = require("express") express = require("express")
url = require("url") url = require("url")
@ -71,9 +72,13 @@ module.exports = class WebServer
meetingID = urlObj.query["meetingID"] meetingID = urlObj.query["meetingID"]
if meetingID? if meetingID?
hooks = Hook.allForMeetingSync(meetingID) # all the hooks that receive events from this meeting
else
hooks = Hook.allGlobalSync() hooks = Hook.allGlobalSync()
hooks = hooks.concat(Hook.findByExternalMeetingIDSync(meetingID))
hooks = _.sortBy(hooks, (hook) -> hook.id)
else
# no meetingID, return all hooks
hooks = Hook.allSync()
msg = "<response><returncode>SUCCESS</returncode><hooks>" msg = "<response><returncode>SUCCESS</returncode><hooks>"
hooks.forEach (hook) -> hooks.forEach (hook) ->