Webhooks: trigger callbacks for recording events too
This commit is contained in:
parent
81f5a109b6
commit
7efb3a18ab
@ -227,9 +227,9 @@ More details
|
|||||||
* Callbacks are always triggered for one event at a time and in order. They are ordered the same way they appear on pubsub (which might not exactly be the order indicated by their timestamps). The timestamps will almost always be ordered as well, but it's not guaranteed.
|
* Callbacks are always triggered for one event at a time and in order. They are ordered the same way they appear on pubsub (which might not exactly be the order indicated by their timestamps). The timestamps will almost always be ordered as well, but it's not guaranteed.
|
||||||
* The application assumes that events are never duplicated on pubsub. If they happen to be duplicated, the callback calls will also be duplicated.
|
* The application assumes that events are never duplicated on pubsub. If they happen to be duplicated, the callback calls will also be duplicated.
|
||||||
* Hooks are only removed if a call to `/destroy` is made or if the callbacks for the hook fail too many times (~12) for a long period of time (~5min). They are never removed otherwise. Valid for both global hooks and hooks for specific meetings.
|
* Hooks are only removed if a call to `/destroy` is made or if the callbacks for the hook fail too many times (~12) for a long period of time (~5min). They are never removed otherwise. Valid for both global hooks and hooks for specific meetings.
|
||||||
* If a meeting is created while the webhooks app is down, callbacks will never be triggered for this meeting. The app needs to detect the create event (`meeting_created_message`) to have a mapping of internal to external meeting IDs.
|
|
||||||
* Mappings are removed after 24 hours of inactivity. If there are no events at all for a given meeting, it will be assumed dead. This is done to prevent data from being stored forever on redis.
|
* Mappings are removed after 24 hours of inactivity. If there are no events at all for a given meeting, it will be assumed dead. This is done to prevent data from being stored forever on redis.
|
||||||
* External URLs are expected to respond with the HTTP status 200, 201 or 202. Anything different from these values will be considered an error and the callback will be called again. This includes URLs that redirect to some other place.
|
* External URLs are expected to respond with the HTTP status 200, 201 or 202. Anything different from these values will be considered an error and the callback will be called again. This includes URLs that redirect to some other place.
|
||||||
|
* If a meeting is created while the webhooks app is down, callbacks will never be triggered for this meeting. The app needs to detect the create event (`meeting_created_message`) to have a mapping of internal to external meeting IDs.
|
||||||
|
|
||||||
Development
|
Development
|
||||||
-----------
|
-----------
|
||||||
|
@ -22,7 +22,21 @@ config.hooks.events or= [
|
|||||||
{ channel: "bigbluebutton:from-bbb-apps:meeting", name: "meeting_created_message" },
|
{ channel: "bigbluebutton:from-bbb-apps:meeting", name: "meeting_created_message" },
|
||||||
{ channel: "bigbluebutton:from-bbb-apps:meeting", name: "meeting_destroyed_event" },
|
{ channel: "bigbluebutton:from-bbb-apps:meeting", name: "meeting_destroyed_event" },
|
||||||
{ channel: "bigbluebutton:from-bbb-apps:users", name: "user_joined_message" },
|
{ channel: "bigbluebutton:from-bbb-apps:users", name: "user_joined_message" },
|
||||||
{ channel: "bigbluebutton:from-bbb-apps:users", name: "user_left_message" }
|
{ channel: "bigbluebutton:from-bbb-apps:users", name: "user_left_message" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "sanity_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "sanity_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "archive_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "archive_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_archive_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_archive_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "process_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "process_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_process_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_process_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "publish_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "publish_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_publish_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_publish_ended" }
|
||||||
]
|
]
|
||||||
|
|
||||||
# Retry intervals for failed attempts for perform callback calls.
|
# Retry intervals for failed attempts for perform callback calls.
|
||||||
@ -33,7 +47,7 @@ config.hooks.retryIntervals = [
|
|||||||
|
|
||||||
# Mappings of internal to external meeting IDs
|
# Mappings of internal to external meeting IDs
|
||||||
config.mappings = {}
|
config.mappings = {}
|
||||||
config.mappings.cleanupInterval = 1000 # in ms
|
config.mappings.cleanupInterval = 10000 # 10 secs, in ms
|
||||||
config.mappings.timeout = 1000*60*60*24 # 24 hours, in ms
|
config.mappings.timeout = 1000*60*60*24 # 24 hours, in ms
|
||||||
|
|
||||||
# Redis
|
# Redis
|
||||||
|
@ -12,11 +12,25 @@ config.server.port = 3005
|
|||||||
|
|
||||||
# Callbacks will be triggered for all the events in this list and only for these events.
|
# Callbacks will be triggered for all the events in this list and only for these events.
|
||||||
config.hooks = {}
|
config.hooks = {}
|
||||||
config.hooks.events or= [
|
config.hooks.events = [
|
||||||
{ channel: "bigbluebutton:from-bbb-apps:meeting", name: "meeting_created_message" },
|
{ channel: "bigbluebutton:from-bbb-apps:meeting", name: "meeting_created_message" },
|
||||||
{ channel: "bigbluebutton:from-bbb-apps:meeting", name: "meeting_destroyed_event" },
|
{ channel: "bigbluebutton:from-bbb-apps:meeting", name: "meeting_destroyed_event" },
|
||||||
{ channel: "bigbluebutton:from-bbb-apps:users", name: "user_joined_message" },
|
{ channel: "bigbluebutton:from-bbb-apps:users", name: "user_joined_message" },
|
||||||
{ channel: "bigbluebutton:from-bbb-apps:users", name: "user_left_message" }
|
{ channel: "bigbluebutton:from-bbb-apps:users", name: "user_left_message" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "sanity_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "sanity_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "archive_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "archive_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_archive_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_archive_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "process_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "process_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_process_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_process_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "publish_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "publish_ended" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_publish_started" },
|
||||||
|
{ channel: "bigbluebutton:from-rap", name: "post_publish_ended" }
|
||||||
]
|
]
|
||||||
|
|
||||||
module.exports = config
|
module.exports = config
|
||||||
|
@ -23,7 +23,11 @@ nextID = 1
|
|||||||
# Hooks can be global, receiving callback calls for events from all meetings on the
|
# Hooks can be global, receiving callback calls for events from all meetings on the
|
||||||
# server, or for a specific meeting. If an `externalMeetingID` is set in the hook,
|
# server, or for a specific meeting. If an `externalMeetingID` is set in the hook,
|
||||||
# it will only receive calls related to this meeting, otherwise it will be global.
|
# it will only receive calls related to this meeting, otherwise it will be global.
|
||||||
# TODO: at some point the queue needs to be cleared, or we need a size limit on it
|
# Events are kept in a queue to be sent in the order they are received.
|
||||||
|
# TODO: The queue should be cleared at some point. The hook is destroyed if too many
|
||||||
|
# callback attempts fail, after ~5min. So the queue is already protected in this case.
|
||||||
|
# But if the requests are going by but taking too long, the queue might be increasing
|
||||||
|
# faster than the callbacks are made.
|
||||||
module.exports = class Hook
|
module.exports = class Hook
|
||||||
|
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
@ -57,6 +57,8 @@ module.exports = class WebHooks
|
|||||||
_processEvent: (message) ->
|
_processEvent: (message) ->
|
||||||
hooks = Hook.allGlobalSync()
|
hooks = Hook.allGlobalSync()
|
||||||
|
|
||||||
|
# TODO: events that happen after the meeting ended will never trigger the hooks
|
||||||
|
# below, since the mapping is removed when the meeting ends
|
||||||
# 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
|
idFromMessage = message.payload?.meeting_id
|
||||||
@ -75,13 +77,17 @@ module.exports = class WebHooks
|
|||||||
Logger.info "WebHooks: subscribed to meetings channel ", channel
|
Logger.info "WebHooks: subscribed to meetings channel ", channel
|
||||||
|
|
||||||
@subscriberMeetings.on "message", (channel, message) =>
|
@subscriberMeetings.on "message", (channel, message) =>
|
||||||
Logger.info "WebHooks: got message on meetings channel [#{channel}]", message
|
|
||||||
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"
|
||||||
|
Logger.info "WebHooks: got create message on meetings channel [#{channel}]", message
|
||||||
IDMapping.addOrUpdateMapping(message.payload?.meeting_id, message.payload?.external_meeting_id)
|
IDMapping.addOrUpdateMapping(message.payload?.meeting_id, message.payload?.external_meeting_id)
|
||||||
else if message.header?.name is "meeting_destroyed_event"
|
|
||||||
IDMapping.removeMapping(message.payload?.meeting_id)
|
# TODO: Temporarily commented because we still need the mapping for recording events,
|
||||||
|
# after the meeting ended.
|
||||||
|
# else if message.header?.name is "meeting_destroyed_event"
|
||||||
|
# Logger.info "WebHooks: got destroy message on meetings channel [#{channel}]", message
|
||||||
|
# IDMapping.removeMapping(message.payload?.meeting_id)
|
||||||
|
|
||||||
catch e
|
catch e
|
||||||
Logger.error.log "WebHooks: error processing the message", JSON.stringify(message), ":", e
|
Logger.error.log "WebHooks: error processing the message", JSON.stringify(message), ":", e
|
||||||
|
@ -41,9 +41,6 @@ module.exports = class WebServer
|
|||||||
callbackURL = urlObj.query["callbackURL"]
|
callbackURL = urlObj.query["callbackURL"]
|
||||||
meetingID = urlObj.query["meetingID"]
|
meetingID = urlObj.query["meetingID"]
|
||||||
|
|
||||||
# TODO: if meetingID is set in the url, check if the meeting exists, otherwise
|
|
||||||
# invalid("invalidMeetingIdentifier", "The meeting ID that you supplied did not match any existing meetings");
|
|
||||||
|
|
||||||
unless callbackURL?
|
unless callbackURL?
|
||||||
respondWithXML(res, config.api.responses.missingParamCallbackURL)
|
respondWithXML(res, config.api.responses.missingParamCallbackURL)
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user