This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/components/message_bus.js.coffee
2013-02-05 14:16:51 -05:00

115 lines
3.1 KiB
CoffeeScript

window.Discourse.MessageBus = ( ->
# http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
uniqueId = -> 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace /[xy]/g, (c)->
r = Math.random()*16 | 0
v = if c == 'x' then r else (r&0x3|0x8)
v.toString(16)
clientId = uniqueId()
responseCallbacks = {}
callbacks = []
queue = []
interval = null
failCount = 0
isHidden = ->
if document.hidden != undefined
document.hidden
else if document.webkitHidden != undefined
document.webkitHidden
else if document.msHidden != undefined
document.msHidden
else if document.mozHidden != undefined
document.mozHidden
else
# fallback to problamatic window.focus
!Discourse.get('hasFocus')
enableLongPolling: true
callbackInterval: 60000
maxPollInterval: (3 * 60 * 1000)
callbacks: callbacks
clientId: clientId
#TODO
stop:
false
# Start polling
start: (opts={})->
poll = =>
if callbacks.length == 0
setTimeout poll, 500
return
data = {}
callbacks.each (c)->
data[c.channel] = if c.last_id == undefined then -1 else c.last_id
gotData = false
@longPoll = $.ajax "/message-bus/#{clientId}/poll?#{if isHidden() || !@enableLongPolling then "dlp=t" else ""}",
data: data
cache: false
dataType: 'json'
type: 'POST'
headers:
'X-SILENCE-LOGGER': 'true'
success: (messages) =>
failCount = 0
messages.each (message) =>
gotData = true
callbacks.each (callback) ->
if callback.channel == message.channel
callback.last_id = message.message_id
callback.func(message.data)
if message["channel"] == "/__status"
callback.last_id = message.data[callback.channel] if message.data[callback.channel] != undefined
return
error:
failCount += 1
complete: =>
if gotData
setTimeout poll, 100
else
interval = @callbackInterval
if failCount > 2
interval = interval * failCount
else if isHidden()
# slowning down stuff a lot when hidden
# we will need to add a lot of fine tuning here
interval = interval * 4
if interval > @maxPollInterval
interval = @maxPollInterval
setTimeout poll, interval
@longPoll = null
return
poll()
return
# Subscribe to a channel
subscribe: (channel,func,lastId)->
callbacks.push {channel:channel, func:func, last_id: lastId}
@longPoll.abort() if @longPoll
# Unsubscribe from a channel
unsubscribe: (channel) ->
# TODO proper globbing
if channel.endsWith("*")
channel = channel.substr(0, channel.length-1)
glob = true
callbacks = callbacks.filter (callback) ->
if glob
callback.channel.substr(0, channel.length) != channel
else
callback.channel != channel
@longPoll.abort() if @longPoll
)()