message_bus 2.0.0.beta.8 → 2.0.0.beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of message_bus might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG +5 -0
- data/README.md +4 -0
- data/lib/message_bus/backends/postgres.rb +1 -1
- data/lib/message_bus/rack/middleware.rb +2 -1
- data/lib/message_bus/version.rb +1 -1
- data/vendor/assets/javascripts/message-bus-ajax.js +1 -0
- data/vendor/assets/javascripts/message-bus.js +1 -0
- metadata +3 -3
- data/vendor/assets/javascripts/message-bus-ajax.js +0 -44
- data/vendor/assets/javascripts/message-bus.js +0 -418
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0974fc7ea256d61e7ecd1b72b3f01413e1fc23b5
|
4
|
+
data.tar.gz: e2c501cfdefd50eebdf55e2ac2b2c097e235cbb0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abd739f0d8bb295cc06c953f90bf8e3b0f12e5f493830c2cd1cebbce3e448deff78f65e06bec78b294740703772f81a772196e6f92bcf2b5fd2911b8fb0e358e
|
7
|
+
data.tar.gz: 48eb3572114789e6d8665d8c09987501f593fccbc03cfbd708349b300428aee081ae0effee0d865ec3415f381d15d92808295a6a2ec0e461bdabec48feaa7c2d
|
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -71,6 +71,10 @@ MessageBus.publish "/channel", "hello", client_ids: ["XXX","YYY"]
|
|
71
71
|
# message bus determines the user ids and groups based on env
|
72
72
|
|
73
73
|
MessageBus.configure(user_id_lookup: proc do |env|
|
74
|
+
# this lookup occurs on JS-client poolings, so that server can retrieve backlog
|
75
|
+
# for the client considering/matching/filtering user_ids set on published messages
|
76
|
+
# if user_id is not set on publish time, any user_id returned here will receive the message
|
77
|
+
|
74
78
|
# return the user id here
|
75
79
|
end)
|
76
80
|
|
@@ -184,7 +184,7 @@ class MessageBus::Postgres::Client
|
|
184
184
|
|
185
185
|
conn.exec 'PREPARE insert_message AS INSERT INTO message_bus (channel, value) VALUES ($1, $2) RETURNING id'
|
186
186
|
conn.exec 'PREPARE clear_global_backlog AS DELETE FROM message_bus WHERE (id <= $1)'
|
187
|
-
conn.exec 'PREPARE clear_channel_backlog AS DELETE FROM message_bus WHERE ((channel = $1) AND (id <= (SELECT id FROM message_bus WHERE ((channel = $1) AND (id <= $2)) ORDER BY id DESC OFFSET $3)))'
|
187
|
+
conn.exec 'PREPARE clear_channel_backlog AS DELETE FROM message_bus WHERE ((channel = $1) AND (id <= (SELECT id FROM message_bus WHERE ((channel = $1) AND (id <= $2)) ORDER BY id DESC LIMIT 1 OFFSET $3)))'
|
188
188
|
conn.exec 'PREPARE channel_backlog AS SELECT id, value FROM message_bus WHERE ((channel = $1) AND (id > $2)) ORDER BY id'
|
189
189
|
conn.exec 'PREPARE global_backlog AS SELECT id, channel, value FROM message_bus WHERE (id > $1) ORDER BY id'
|
190
190
|
conn.exec "PREPARE expire AS DELETE FROM message_bus WHERE added_at < CURRENT_TIMESTAMP - ($1::text || ' seconds')::interval"
|
@@ -95,7 +95,8 @@ class MessageBus::Rack::Middleware
|
|
95
95
|
end
|
96
96
|
else
|
97
97
|
request = Rack::Request.new(env)
|
98
|
-
|
98
|
+
is_json = request.content_type && request.content_type.include?('application/json')
|
99
|
+
data = is_json ? JSON.parse(request.body.read) : request.POST
|
99
100
|
data.each do |k,v|
|
100
101
|
if k == "__seq".freeze
|
101
102
|
client.seq = v.to_i
|
data/lib/message_bus/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
../../../assets/message-bus-ajax.js
|
@@ -0,0 +1 @@
|
|
1
|
+
../../../assets/message-bus.js
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: message_bus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0.beta.
|
4
|
+
version: 2.0.0.beta.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
140
|
version: 1.3.1
|
141
141
|
requirements: []
|
142
142
|
rubyforge_project:
|
143
|
-
rubygems_version: 2.
|
143
|
+
rubygems_version: 2.5.1
|
144
144
|
signing_key:
|
145
145
|
specification_version: 4
|
146
146
|
summary: ''
|
@@ -1,44 +0,0 @@
|
|
1
|
-
// A bare-bones implementation of $.ajax that MessageBus will use
|
2
|
-
// as a fallback if jQuery is not present
|
3
|
-
//
|
4
|
-
// Only implements methods & options used by MessageBus
|
5
|
-
(function(global, undefined) {
|
6
|
-
'use strict';
|
7
|
-
if (!global.MessageBus){
|
8
|
-
throw new Error("MessageBus must be loaded before the ajax adapter");
|
9
|
-
}
|
10
|
-
|
11
|
-
var cacheBuster = Math.random() * 10000 | 0;
|
12
|
-
|
13
|
-
global.MessageBus.ajax = function(options){
|
14
|
-
var XHRImpl = (global.MessageBus && global.MessageBus.xhrImplementation) || global.XMLHttpRequest;
|
15
|
-
var xhr = new XHRImpl();
|
16
|
-
xhr.dataType = options.dataType;
|
17
|
-
var url = options.url;
|
18
|
-
if (!options.cache){
|
19
|
-
url += ((-1 == url.indexOf('?')) ? '?' : '&') + '_=' + (cacheBuster++)
|
20
|
-
}
|
21
|
-
xhr.open('POST', url);
|
22
|
-
for (var name in options.headers){
|
23
|
-
xhr.setRequestHeader(name, options.headers[name]);
|
24
|
-
}
|
25
|
-
xhr.setRequestHeader('Content-Type', 'application/json');
|
26
|
-
if (options.messageBus.chunked){
|
27
|
-
options.messageBus.onProgressListener(xhr);
|
28
|
-
}
|
29
|
-
xhr.onreadystatechange = function(){
|
30
|
-
if (xhr.readyState === 4){
|
31
|
-
var status = xhr.status;
|
32
|
-
if (status >= 200 && status < 300 || status === 304){
|
33
|
-
options.success(xhr.responseText);
|
34
|
-
} else {
|
35
|
-
options.error(xhr, xhr.statusText);
|
36
|
-
}
|
37
|
-
options.complete();
|
38
|
-
}
|
39
|
-
}
|
40
|
-
xhr.send(JSON.stringify(options.data));
|
41
|
-
return xhr;
|
42
|
-
};
|
43
|
-
|
44
|
-
})(window);
|
@@ -1,418 +0,0 @@
|
|
1
|
-
/*jshint bitwise: false*/
|
2
|
-
(function(global, document, undefined) {
|
3
|
-
'use strict';
|
4
|
-
var previousMessageBus = global.MessageBus;
|
5
|
-
|
6
|
-
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
|
7
|
-
var callbacks, clientId, failCount, shouldLongPoll, queue, responseCallbacks, uniqueId, baseUrl;
|
8
|
-
var me, started, stopped, longPoller, pollTimeout, paused, later, jQuery, interval, chunkedBackoff;
|
9
|
-
|
10
|
-
uniqueId = function() {
|
11
|
-
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
12
|
-
var r, v;
|
13
|
-
r = Math.random() * 16 | 0;
|
14
|
-
v = c === 'x' ? r : (r & 0x3 | 0x8);
|
15
|
-
return v.toString(16);
|
16
|
-
});
|
17
|
-
};
|
18
|
-
|
19
|
-
clientId = uniqueId();
|
20
|
-
responseCallbacks = {};
|
21
|
-
callbacks = [];
|
22
|
-
queue = [];
|
23
|
-
interval = null;
|
24
|
-
failCount = 0;
|
25
|
-
baseUrl = "/";
|
26
|
-
paused = false;
|
27
|
-
later = [];
|
28
|
-
chunkedBackoff = 0;
|
29
|
-
jQuery = global.jQuery;
|
30
|
-
var hiddenProperty;
|
31
|
-
|
32
|
-
(function(){
|
33
|
-
var prefixes = ["","webkit","ms","moz"];
|
34
|
-
for(var i=0; i<prefixes.length; i++) {
|
35
|
-
var prefix = prefixes[i];
|
36
|
-
var check = prefix + (prefix === "" ? "hidden" : "Hidden");
|
37
|
-
if(document[check] !== undefined ){
|
38
|
-
hiddenProperty = check;
|
39
|
-
}
|
40
|
-
}
|
41
|
-
})();
|
42
|
-
|
43
|
-
var isHidden = function() {
|
44
|
-
if (hiddenProperty !== undefined){
|
45
|
-
return document[hiddenProperty];
|
46
|
-
} else {
|
47
|
-
return !document.hasFocus;
|
48
|
-
}
|
49
|
-
};
|
50
|
-
|
51
|
-
var hasonprogress = (new XMLHttpRequest()).onprogress === null;
|
52
|
-
var allowChunked = function(){
|
53
|
-
return me.enableChunkedEncoding && hasonprogress;
|
54
|
-
};
|
55
|
-
|
56
|
-
shouldLongPoll = function() {
|
57
|
-
return me.alwaysLongPoll || !isHidden();
|
58
|
-
};
|
59
|
-
|
60
|
-
var totalAjaxFailures = 0;
|
61
|
-
var totalAjaxCalls = 0;
|
62
|
-
var lastAjax;
|
63
|
-
|
64
|
-
var processMessages = function(messages) {
|
65
|
-
var gotData = false;
|
66
|
-
if (!messages) return false; // server unexpectedly closed connection
|
67
|
-
|
68
|
-
for (var i=0; i<messages.length; i++) {
|
69
|
-
var message = messages[i];
|
70
|
-
gotData = true;
|
71
|
-
for (var j=0; j<callbacks.length; j++) {
|
72
|
-
var callback = callbacks[j];
|
73
|
-
if (callback.channel === message.channel) {
|
74
|
-
callback.last_id = message.message_id;
|
75
|
-
try {
|
76
|
-
callback.func(message.data);
|
77
|
-
}
|
78
|
-
catch(e){
|
79
|
-
if(console.log) {
|
80
|
-
console.log("MESSAGE BUS FAIL: callback " + callback.channel + " caused exception " + e.message);
|
81
|
-
}
|
82
|
-
}
|
83
|
-
}
|
84
|
-
if (message.channel === "/__status") {
|
85
|
-
if (message.data[callback.channel] !== undefined) {
|
86
|
-
callback.last_id = message.data[callback.channel];
|
87
|
-
}
|
88
|
-
}
|
89
|
-
}
|
90
|
-
}
|
91
|
-
|
92
|
-
return gotData;
|
93
|
-
};
|
94
|
-
|
95
|
-
var reqSuccess = function(messages) {
|
96
|
-
failCount = 0;
|
97
|
-
if (paused) {
|
98
|
-
if (messages) {
|
99
|
-
for (var i=0; i<messages.length; i++) {
|
100
|
-
later.push(messages[i]);
|
101
|
-
}
|
102
|
-
}
|
103
|
-
} else {
|
104
|
-
return processMessages(messages);
|
105
|
-
}
|
106
|
-
return false;
|
107
|
-
};
|
108
|
-
|
109
|
-
longPoller = function(poll,data){
|
110
|
-
var gotData = false;
|
111
|
-
var aborted = false;
|
112
|
-
lastAjax = new Date();
|
113
|
-
totalAjaxCalls += 1;
|
114
|
-
data.__seq = totalAjaxCalls;
|
115
|
-
|
116
|
-
var longPoll = shouldLongPoll() && me.enableLongPolling;
|
117
|
-
var chunked = longPoll && allowChunked();
|
118
|
-
if (chunkedBackoff > 0) {
|
119
|
-
chunkedBackoff--;
|
120
|
-
chunked = false;
|
121
|
-
}
|
122
|
-
|
123
|
-
var headers = {
|
124
|
-
'X-SILENCE-LOGGER': 'true'
|
125
|
-
};
|
126
|
-
for (var name in me.headers){
|
127
|
-
headers[name] = me.headers[name];
|
128
|
-
}
|
129
|
-
|
130
|
-
if (!chunked){
|
131
|
-
headers["Dont-Chunk"] = 'true';
|
132
|
-
}
|
133
|
-
|
134
|
-
var dataType = chunked ? "text" : "json";
|
135
|
-
|
136
|
-
var handle_progress = function(payload, position) {
|
137
|
-
|
138
|
-
var separator = "\r\n|\r\n";
|
139
|
-
var endChunk = payload.indexOf(separator, position);
|
140
|
-
|
141
|
-
if (endChunk === -1) {
|
142
|
-
return position;
|
143
|
-
}
|
144
|
-
|
145
|
-
var chunk = payload.substring(position, endChunk);
|
146
|
-
chunk = chunk.replace(/\r\n\|\|\r\n/g, separator);
|
147
|
-
|
148
|
-
try {
|
149
|
-
reqSuccess(JSON.parse(chunk));
|
150
|
-
} catch(e) {
|
151
|
-
if (console.log) {
|
152
|
-
console.log("FAILED TO PARSE CHUNKED REPLY");
|
153
|
-
console.log(data);
|
154
|
-
}
|
155
|
-
}
|
156
|
-
|
157
|
-
return handle_progress(payload, endChunk + separator.length);
|
158
|
-
}
|
159
|
-
|
160
|
-
var disableChunked = function(){
|
161
|
-
if (me.longPoll) {
|
162
|
-
me.longPoll.abort();
|
163
|
-
chunkedBackoff = 30;
|
164
|
-
}
|
165
|
-
};
|
166
|
-
|
167
|
-
var setOnProgressListener = function(xhr) {
|
168
|
-
var position = 0;
|
169
|
-
// if it takes longer than 3000 ms to get first chunk, we have some proxy
|
170
|
-
// this is messing with us, so just backoff from using chunked for now
|
171
|
-
var chunkedTimeout = setTimeout(disableChunked,3000);
|
172
|
-
xhr.onprogress = function () {
|
173
|
-
clearTimeout(chunkedTimeout);
|
174
|
-
if(xhr.getResponseHeader('Content-Type') === 'application/json; charset=utf-8') {
|
175
|
-
// not chunked we are sending json back
|
176
|
-
chunked = false;
|
177
|
-
return;
|
178
|
-
}
|
179
|
-
position = handle_progress(xhr.responseText, position);
|
180
|
-
}
|
181
|
-
};
|
182
|
-
if (!me.ajax){
|
183
|
-
throw new Error("Either jQuery or the ajax adapter must be loaded");
|
184
|
-
}
|
185
|
-
var req = me.ajax({
|
186
|
-
url: me.baseUrl + "message-bus/" + me.clientId + "/poll" + (!longPoll ? "?dlp=t" : ""),
|
187
|
-
data: data,
|
188
|
-
cache: false,
|
189
|
-
dataType: dataType,
|
190
|
-
type: 'POST',
|
191
|
-
headers: headers,
|
192
|
-
messageBus: {
|
193
|
-
chunked: chunked,
|
194
|
-
onProgressListener: function(xhr) {
|
195
|
-
var position = 0;
|
196
|
-
// if it takes longer than 3000 ms to get first chunk, we have some proxy
|
197
|
-
// this is messing with us, so just backoff from using chunked for now
|
198
|
-
var chunkedTimeout = setTimeout(disableChunked,3000);
|
199
|
-
return xhr.onprogress = function () {
|
200
|
-
clearTimeout(chunkedTimeout);
|
201
|
-
if(xhr.getResponseHeader('Content-Type') === 'application/json; charset=utf-8') {
|
202
|
-
chunked = false; // not chunked, we are sending json back
|
203
|
-
} else {
|
204
|
-
position = handle_progress(xhr.responseText, position);
|
205
|
-
}
|
206
|
-
}
|
207
|
-
}
|
208
|
-
},
|
209
|
-
xhr: function() {
|
210
|
-
var xhr = jQuery.ajaxSettings.xhr();
|
211
|
-
if (!chunked) {
|
212
|
-
return xhr;
|
213
|
-
}
|
214
|
-
this.messageBus.onProgressListener(xhr);
|
215
|
-
return xhr;
|
216
|
-
},
|
217
|
-
success: function(messages) {
|
218
|
-
if (!chunked) {
|
219
|
-
// we may have requested text so jQuery will not parse
|
220
|
-
if (typeof(messages) === "string") {
|
221
|
-
messages = JSON.parse(messages);
|
222
|
-
}
|
223
|
-
gotData = reqSuccess(messages);
|
224
|
-
}
|
225
|
-
},
|
226
|
-
error: function(xhr, textStatus, err) {
|
227
|
-
if(textStatus === "abort") {
|
228
|
-
aborted = true;
|
229
|
-
} else {
|
230
|
-
failCount += 1;
|
231
|
-
totalAjaxFailures += 1;
|
232
|
-
}
|
233
|
-
},
|
234
|
-
complete: function() {
|
235
|
-
var interval;
|
236
|
-
try {
|
237
|
-
if (gotData || aborted) {
|
238
|
-
interval = 100;
|
239
|
-
} else {
|
240
|
-
interval = me.callbackInterval;
|
241
|
-
if (failCount > 2) {
|
242
|
-
interval = interval * failCount;
|
243
|
-
} else if (!shouldLongPoll()) {
|
244
|
-
interval = me.backgroundCallbackInterval;
|
245
|
-
}
|
246
|
-
if (interval > me.maxPollInterval) {
|
247
|
-
interval = me.maxPollInterval;
|
248
|
-
}
|
249
|
-
|
250
|
-
interval -= (new Date() - lastAjax);
|
251
|
-
|
252
|
-
if (interval < 100) {
|
253
|
-
interval = 100;
|
254
|
-
}
|
255
|
-
}
|
256
|
-
} catch(e) {
|
257
|
-
if(console.log && e.message) {
|
258
|
-
console.log("MESSAGE BUS FAIL: " + e.message);
|
259
|
-
}
|
260
|
-
}
|
261
|
-
|
262
|
-
pollTimeout = setTimeout(function(){pollTimeout=null; poll();}, interval);
|
263
|
-
me.longPoll = null;
|
264
|
-
}
|
265
|
-
});
|
266
|
-
|
267
|
-
return req;
|
268
|
-
};
|
269
|
-
|
270
|
-
me = {
|
271
|
-
enableChunkedEncoding: true,
|
272
|
-
enableLongPolling: true,
|
273
|
-
callbackInterval: 15000,
|
274
|
-
backgroundCallbackInterval: 60000,
|
275
|
-
maxPollInterval: 3 * 60 * 1000,
|
276
|
-
callbacks: callbacks,
|
277
|
-
clientId: clientId,
|
278
|
-
alwaysLongPoll: false,
|
279
|
-
baseUrl: baseUrl,
|
280
|
-
headers: {},
|
281
|
-
ajax: (jQuery && jQuery.ajax),
|
282
|
-
noConflict: function(){
|
283
|
-
global.MessageBus = global.MessageBus.previousMessageBus;
|
284
|
-
return this;
|
285
|
-
},
|
286
|
-
diagnostics: function(){
|
287
|
-
console.log("Stopped: " + stopped + " Started: " + started);
|
288
|
-
console.log("Current callbacks");
|
289
|
-
console.log(callbacks);
|
290
|
-
console.log("Total ajax calls: " + totalAjaxCalls + " Recent failure count: " + failCount + " Total failures: " + totalAjaxFailures);
|
291
|
-
console.log("Last ajax call: " + (new Date() - lastAjax) / 1000 + " seconds ago") ;
|
292
|
-
},
|
293
|
-
|
294
|
-
pause: function() {
|
295
|
-
paused = true;
|
296
|
-
},
|
297
|
-
|
298
|
-
resume: function() {
|
299
|
-
paused = false;
|
300
|
-
processMessages(later);
|
301
|
-
later = [];
|
302
|
-
},
|
303
|
-
|
304
|
-
stop: function() {
|
305
|
-
stopped = true;
|
306
|
-
started = false;
|
307
|
-
},
|
308
|
-
|
309
|
-
// Start polling
|
310
|
-
start: function() {
|
311
|
-
var poll, delayPollTimeout;
|
312
|
-
|
313
|
-
if (started) return;
|
314
|
-
started = true;
|
315
|
-
stopped = false;
|
316
|
-
|
317
|
-
poll = function() {
|
318
|
-
var data;
|
319
|
-
|
320
|
-
if(stopped) {
|
321
|
-
return;
|
322
|
-
}
|
323
|
-
|
324
|
-
if (callbacks.length === 0) {
|
325
|
-
if(!delayPollTimeout) {
|
326
|
-
delayPollTimeout = setTimeout(function(){ delayPollTimeout = null; poll();}, 500);
|
327
|
-
}
|
328
|
-
return;
|
329
|
-
}
|
330
|
-
|
331
|
-
data = {};
|
332
|
-
for (var i=0;i<callbacks.length;i++) {
|
333
|
-
data[callbacks[i].channel] = callbacks[i].last_id;
|
334
|
-
}
|
335
|
-
|
336
|
-
me.longPoll = longPoller(poll,data);
|
337
|
-
};
|
338
|
-
|
339
|
-
|
340
|
-
// monitor visibility, issue a new long poll when the page shows
|
341
|
-
if(document.addEventListener && 'hidden' in document){
|
342
|
-
me.visibilityEvent = global.document.addEventListener('visibilitychange', function(){
|
343
|
-
if(!document.hidden && !me.longPoll && pollTimeout){
|
344
|
-
clearTimeout(pollTimeout);
|
345
|
-
pollTimeout = null;
|
346
|
-
poll();
|
347
|
-
}
|
348
|
-
});
|
349
|
-
}
|
350
|
-
|
351
|
-
poll();
|
352
|
-
},
|
353
|
-
|
354
|
-
// Subscribe to a channel
|
355
|
-
subscribe: function(channel, func, lastId) {
|
356
|
-
|
357
|
-
if(!started && !stopped){
|
358
|
-
me.start();
|
359
|
-
}
|
360
|
-
|
361
|
-
if (typeof(lastId) !== "number" || lastId < -1){
|
362
|
-
lastId = -1;
|
363
|
-
}
|
364
|
-
callbacks.push({
|
365
|
-
channel: channel,
|
366
|
-
func: func,
|
367
|
-
last_id: lastId
|
368
|
-
});
|
369
|
-
if (me.longPoll) {
|
370
|
-
me.longPoll.abort();
|
371
|
-
}
|
372
|
-
|
373
|
-
return func;
|
374
|
-
},
|
375
|
-
|
376
|
-
// Unsubscribe from a channel
|
377
|
-
unsubscribe: function(channel, func) {
|
378
|
-
// TODO allow for globbing in the middle of a channel name
|
379
|
-
// like /something/*/something
|
380
|
-
// at the moment we only support globbing /something/*
|
381
|
-
var glob;
|
382
|
-
if (channel.indexOf("*", channel.length - 1) !== -1) {
|
383
|
-
channel = channel.substr(0, channel.length - 1);
|
384
|
-
glob = true;
|
385
|
-
}
|
386
|
-
|
387
|
-
var removed = false;
|
388
|
-
|
389
|
-
for (var i=callbacks.length-1; i>=0; i--) {
|
390
|
-
|
391
|
-
var callback = callbacks[i];
|
392
|
-
var keep;
|
393
|
-
|
394
|
-
if (glob) {
|
395
|
-
keep = callback.channel.substr(0, channel.length) !== channel;
|
396
|
-
} else {
|
397
|
-
keep = callback.channel !== channel;
|
398
|
-
}
|
399
|
-
|
400
|
-
if(!keep && func && callback.func !== func){
|
401
|
-
keep = true;
|
402
|
-
}
|
403
|
-
|
404
|
-
if (!keep) {
|
405
|
-
callbacks.splice(i,1);
|
406
|
-
removed = true;
|
407
|
-
}
|
408
|
-
}
|
409
|
-
|
410
|
-
if (removed && me.longPoll) {
|
411
|
-
me.longPoll.abort();
|
412
|
-
}
|
413
|
-
|
414
|
-
return removed;
|
415
|
-
}
|
416
|
-
};
|
417
|
-
global.MessageBus = me;
|
418
|
-
})(window, document);
|