jam-cloud/web/app/assets/javascripts/subscription_utils.js.coffee

131 lines
3.6 KiB
CoffeeScript

#
# Common utility functions to help deal with subscriptions to the server
#
$ = jQuery
context = window
context.JK ||= {};
class SubscriptionUtils
constructor: () ->
@logger = context.JK.logger
@msgFactory = context.JK.MessageFactory;
@subscriptions = {}
@events = context.JK.EVENTS;
@reconnectRegistrationTimeout = null
this.init()
init: () =>
# once JamKazam is fully loaded, watch for SUBSCRIPTION_MESSAGE events
$(document).on('JAMKAZAM_READY', this.registerWithGateway)
genKey:(type, id) =>
type + ":" + id
test: () =>
this.subscribe('test', '1')
this.subscribe('test', '2')
reregister: () =>
# re-register all existing watches
@reconnectRegistrationTimeout = null
if context.JK.dlen(@subscriptions) > 0
bulkSubscribe = []
types = []
ids = []
for key, watch of @subscriptions
bits = key.split(':')
type = bits[0]
id = bits[1]
types.push(type)
ids.push(id)
# bulkSubscribe.push({type: type, id:id})
# send a special message which contains all subscriptions in one message
msg = @msgFactory.subscribeBulk(types, ids)
context.JK.JamServer.send(msg)
# whenever we reconnect, set a timer to automatically re-subscribe to any outstanding subscriptions
onConnectionUp: () =>
#this.test()
if @reconnectRegistrationTimeout?
clearTimeout(@reconnectRegistrationTimeout)
if context.JK.dlen(@subscriptions) > 0
@reconnectRegistrationTimeout = setTimeout(this.reregister, 1000) # re-register after 1 second, to prevent excessive messaging to server
onConnectionDown: () =>
if @reconnectRegistrationTimeout?
clearTimeout(@reconnectRegistrationTimeout)
registerWithGateway: () =>
context.JK.JamServer.registerMessageCallback(context.JK.MessageType.SUBSCRIPTION_MESSAGE, this.onSubscriptionMessage);
$server = context.JK.JamServer.get$Server()
$server.on(@events.CONNECTION_UP, this.onConnectionUp)
$server.on(@events.CONNECTION_DOWN, this.onConnectionDown)
onSubscriptionMessage: (header, payload) =>
console.log("onSubscriptionMessage", payload, header)
key = this.genKey(payload.type, payload.id)
watch = @subscriptions[key]
if watch
watch.triggerHandler(@events.SUBSCRIBE_NOTIFICATION, {type:payload.type, id: payload.id, body: JSON.parse(payload.body)})
else
@logger.warn("unable to find subscription for #{key}")
# call subscribe, and use the returned object to listen for events of name context.JK.EVENTS.SUBSCRIBE_NOTIFICATION
subscribe: (type, id) =>
id = id.toString()
key = this.genKey(type, id)
@logger.debug("subscribing for any notifications for #{key}")
watch = @subscriptions[key]
unless watch?
watch = $({type: type, id: id})
@subscriptions[key] = watch
# tell server we want messages for this entity
msg = @msgFactory.subscribe(type, id)
context.JK.JamServer.send(msg)
# watch can be used to watch for events using jquery
watch
# TODO: this should not send a unsubscribe message to the server it's the last listener for the specific type/id combo
unsubscribe: (type, id) =>
id = id.toString()
key = this.genKey(type, id)
@logger.debug("unsubscribing for any notifications for #{key}")
watch = @subscriptions[key]
delete @subscriptions[key]
# tell server we don't want any more messages for this entity
msg = @msgFactory.unsubscribe(type, id)
context.JK.JamServer.send(msg)
if watch
# unattach any events
watch.off();
watch
# global instance
context.JK.SubscriptionUtils = new SubscriptionUtils()