115 lines
3.1 KiB
CoffeeScript
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
|
|
)()
|