|
1 | | -/*jshint bitwise: false*/ |
2 | | - |
3 | | -/** |
4 | | - Message Bus functionality. |
5 | | -
|
6 | | - @class MessageBus |
7 | | - @namespace Discourse |
8 | | - @module Discourse |
9 | | -**/ |
10 | | -Discourse.MessageBus = (function() { |
11 | | - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript |
12 | | - var callbacks, clientId, failCount, interval, shouldLongPoll, queue, responseCallbacks, uniqueId, baseUrl; |
13 | | - var me; |
14 | | - |
15 | | - uniqueId = function() { |
16 | | - return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { |
17 | | - var r, v; |
18 | | - r = Math.random() * 16 | 0; |
19 | | - v = c === 'x' ? r : (r & 0x3 | 0x8); |
20 | | - return v.toString(16); |
21 | | - }); |
22 | | - }; |
23 | | - |
24 | | - clientId = uniqueId(); |
25 | | - responseCallbacks = {}; |
26 | | - callbacks = []; |
27 | | - queue = []; |
28 | | - interval = null; |
29 | | - failCount = 0; |
30 | | - baseUrl = "/"; |
31 | | - |
32 | | - var isHidden = function() { |
33 | | - if (document.hidden !== void 0) { |
34 | | - return document.hidden; |
35 | | - } else if (document.webkitHidden !== void 0) { |
36 | | - return document.webkitHidden; |
37 | | - } else if (document.msHidden !== void 0) { |
38 | | - return document.msHidden; |
39 | | - } else if (document.mozHidden !== void 0) { |
40 | | - return document.mozHidden; |
41 | | - } else { |
42 | | - // problamatic fallback |
43 | | - return !document.hasFocus; |
44 | | - } |
45 | | - }; |
46 | | - |
47 | | - shouldLongPoll = function() { |
48 | | - return me.alwaysLongPoll || !isHidden(); |
49 | | - }; |
50 | | - |
51 | | - me = { |
52 | | - enableLongPolling: true, |
53 | | - callbackInterval: 60000, |
54 | | - maxPollInterval: 3 * 60 * 1000, |
55 | | - callbacks: callbacks, |
56 | | - clientId: clientId, |
57 | | - alwaysLongPoll: false, |
58 | | - stop: false, |
59 | | - baseUrl: baseUrl, |
60 | | - |
61 | | - // Start polling |
62 | | - start: function(opts) { |
63 | | - var poll, |
64 | | - _this = this; |
65 | | - if (!opts) opts = {}; |
66 | | - |
67 | | - poll = function() { |
68 | | - var data, gotData; |
69 | | - if (callbacks.length === 0) { |
70 | | - setTimeout(poll, 500); |
71 | | - return; |
72 | | - } |
73 | | - data = {}; |
74 | | - _.each(callbacks, function(callback) { |
75 | | - data[callback.channel] = callback.last_id; |
76 | | - }); |
77 | | - gotData = false; |
78 | | - _this.longPoll = $.ajax(baseUrl + "message-bus/" + clientId + "/poll?" + (!shouldLongPoll() || !_this.enableLongPolling ? "dlp=t" : ""), { |
79 | | - data: data, |
80 | | - cache: false, |
81 | | - dataType: 'json', |
82 | | - type: 'POST', |
83 | | - headers: { |
84 | | - 'X-SILENCE-LOGGER': 'true' |
85 | | - }, |
86 | | - success: function(messages) { |
87 | | - failCount = 0; |
88 | | - _.each(messages,function(message) { |
89 | | - gotData = true; |
90 | | - _.each(callbacks, function(callback) { |
91 | | - if (callback.channel === message.channel) { |
92 | | - callback.last_id = message.message_id; |
93 | | - callback.func(message.data); |
94 | | - } |
95 | | - if (message.channel === "/__status") { |
96 | | - if (message.data[callback.channel] !== undefined) { |
97 | | - callback.last_id = message.data[callback.channel]; |
98 | | - } |
99 | | - } |
100 | | - }); |
101 | | - }); |
102 | | - }, |
103 | | - error: failCount += 1, |
104 | | - complete: function() { |
105 | | - if (gotData) { |
106 | | - setTimeout(poll, 100); |
107 | | - } else { |
108 | | - interval = _this.callbackInterval; |
109 | | - if (failCount > 2) { |
110 | | - interval = interval * failCount; |
111 | | - } else if (!shouldLongPoll()) { |
112 | | - // slowning down stuff a lot when hidden |
113 | | - // we will need to add a lot of fine tuning here |
114 | | - interval = interval * 4; |
115 | | - } |
116 | | - if (interval > _this.maxPollInterval) { |
117 | | - interval = _this.maxPollInterval; |
118 | | - } |
119 | | - setTimeout(poll, interval); |
120 | | - } |
121 | | - _this.longPoll = null; |
122 | | - } |
123 | | - }); |
124 | | - }; |
125 | | - poll(); |
126 | | - }, |
127 | | - |
128 | | - // Subscribe to a channel |
129 | | - subscribe: function(channel, func, lastId) { |
130 | | - if (typeof(lastId) !== "number" || lastId < -1){ |
131 | | - lastId = -1; |
132 | | - } |
133 | | - callbacks.push({ |
134 | | - channel: channel, |
135 | | - func: func, |
136 | | - last_id: lastId |
137 | | - }); |
138 | | - if (this.longPoll) { |
139 | | - return this.longPoll.abort(); |
140 | | - } |
141 | | - }, |
142 | | - |
143 | | - // Unsubscribe from a channel |
144 | | - unsubscribe: function(channel) { |
145 | | - // TODO proper globbing |
146 | | - var glob; |
147 | | - if (channel.indexOf("*", channel.length - 1) !== -1) { |
148 | | - channel = channel.substr(0, channel.length - 1); |
149 | | - glob = true; |
150 | | - } |
151 | | - callbacks = $.grep(callbacks,function(callback) { |
152 | | - if (glob) { |
153 | | - return callback.channel.substr(0, channel.length) !== channel; |
154 | | - } else { |
155 | | - return callback.channel !== channel; |
156 | | - } |
157 | | - }); |
158 | | - if (this.longPoll) { |
159 | | - return this.longPoll.abort(); |
160 | | - } |
161 | | - } |
162 | | - }; |
163 | | - |
164 | | - return me; |
165 | | -})(); |
| 1 | +Discourse.MessageBus = window.MessageBus; |
0 commit comments