message_bus 1.1.1 → 2.0.0.beta.1
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 +8 -0
- data/README.md +49 -8
- data/assets/message-bus.js +111 -25
- data/examples/chat/chat.rb +2 -0
- data/examples/chat/docker_container/chat.yml +22 -10
- data/examples/chat/docker_container/update_chat +2 -2
- data/lib/message_bus.rb +10 -13
- data/lib/message_bus/client.rb +105 -27
- data/lib/message_bus/connection_manager.rb +10 -27
- data/lib/message_bus/rack/middleware.rb +29 -8
- data/lib/message_bus/rails/railtie.rb +6 -3
- data/lib/message_bus/version.rb +1 -1
- data/spec/lib/fake_async_middleware.rb +7 -0
- data/spec/lib/{assets → message_bus/assets}/asset_encoding_spec.rb +1 -1
- data/spec/lib/{client_spec.rb → message_bus/client_spec.rb} +78 -0
- data/spec/lib/{connection_manager_spec.rb → message_bus/connection_manager_spec.rb} +0 -0
- data/spec/lib/{multi_process_spec.rb → message_bus/multi_process_spec.rb} +0 -0
- data/spec/lib/{middleware_spec.rb → message_bus/rack/middleware_spec.rb} +2 -89
- data/spec/lib/{redis → message_bus/redis}/reliable_pub_sub_spec.rb +4 -3
- data/spec/lib/{timer_thread_spec.rb → message_bus/timer_thread_spec.rb} +6 -22
- data/spec/spec_helper.rb +6 -1
- data/vendor/assets/javascripts/message-bus.js +111 -25
- metadata +19 -24
- data/lib/message_bus/message_handler.rb +0 -26
- data/spec/lib/handlers/demo_message_handler.rb +0 -5
- data/spec/lib/message_handler_spec.rb +0 -39
File without changes
|
File without changes
|
@@ -79,51 +79,12 @@ describe MessageBus::Rack::Middleware do
|
|
79
79
|
@bus.long_polling_interval = 10
|
80
80
|
s = Time.now.to_f * 1000
|
81
81
|
post "/message-bus/ABC", '/foo' => nil
|
82
|
-
|
82
|
+
# allow for some jitter
|
83
|
+
(Time.now.to_f * 1000 - s).should < 50
|
83
84
|
ensure
|
84
85
|
@bus.long_polling_interval = 5000
|
85
86
|
end
|
86
87
|
end
|
87
|
-
|
88
|
-
it "should support batch filtering" do
|
89
|
-
bus = @bus
|
90
|
-
async_middleware = @async_middleware
|
91
|
-
|
92
|
-
bus.user_id_lookup do |env|
|
93
|
-
1
|
94
|
-
end
|
95
|
-
|
96
|
-
bus.around_client_batch("/demo") do |message, user_ids, callback|
|
97
|
-
begin
|
98
|
-
Thread.current["test"] = user_ids
|
99
|
-
callback.call
|
100
|
-
ensure
|
101
|
-
Thread.current["test"] = nil
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
test = nil
|
106
|
-
|
107
|
-
bus.client_filter("/demo") do |user_id, message|
|
108
|
-
test = Thread.current["test"]
|
109
|
-
message
|
110
|
-
end
|
111
|
-
|
112
|
-
client_id = "ABCD"
|
113
|
-
|
114
|
-
id = bus.publish("/demo", "test")
|
115
|
-
|
116
|
-
Thread.new do
|
117
|
-
wait_for(2000) { async_middleware.in_async? }
|
118
|
-
bus.publish "/demo", "test"
|
119
|
-
end
|
120
|
-
|
121
|
-
post "/message-bus/#{client_id}", {
|
122
|
-
'/demo' => id
|
123
|
-
}
|
124
|
-
|
125
|
-
test.should == [1]
|
126
|
-
end
|
127
88
|
end
|
128
89
|
|
129
90
|
describe "thin async" do
|
@@ -304,54 +265,6 @@ describe MessageBus::Rack::Middleware do
|
|
304
265
|
parsed.length.should == 1
|
305
266
|
end
|
306
267
|
|
307
|
-
|
308
|
-
it "should filter by client_filter correctly" do
|
309
|
-
id = @bus.publish("/filter", "test")
|
310
|
-
uid = 0
|
311
|
-
|
312
|
-
@bus.user_id_lookup do |env|
|
313
|
-
uid
|
314
|
-
end
|
315
|
-
|
316
|
-
@bus.client_filter("/filter") do |user_id, message|
|
317
|
-
if user_id == 0
|
318
|
-
message = message.dup
|
319
|
-
message.data += "_filter"
|
320
|
-
message
|
321
|
-
elsif user_id == 1
|
322
|
-
message
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
client_id = "ABCD"
|
327
|
-
|
328
|
-
post "/message-bus/#{client_id}", {
|
329
|
-
'/filter' => id - 1
|
330
|
-
}
|
331
|
-
|
332
|
-
parsed = JSON.parse(last_response.body)
|
333
|
-
parsed[0]['data'].should == "test_filter"
|
334
|
-
|
335
|
-
uid = 1
|
336
|
-
|
337
|
-
post "/message-bus/#{client_id}", {
|
338
|
-
'/filter' => id - 1
|
339
|
-
}
|
340
|
-
|
341
|
-
parsed = JSON.parse(last_response.body)
|
342
|
-
parsed.length.should == 1
|
343
|
-
parsed[0]["data"].should == "test"
|
344
|
-
|
345
|
-
uid = 2
|
346
|
-
|
347
|
-
post "/message-bus/#{client_id}", {
|
348
|
-
'/filter' => id - 1
|
349
|
-
}
|
350
|
-
|
351
|
-
parsed = JSON.parse(last_response.body)
|
352
|
-
parsed.length.should == 0
|
353
|
-
end
|
354
|
-
|
355
268
|
it "should filter by group correctly" do
|
356
269
|
id =@bus.publish("/foo", "test", group_ids: [3,4,5])
|
357
270
|
@bus.group_ids_lookup do |env|
|
@@ -13,15 +13,16 @@ describe MessageBus::Redis::ReliablePubSub do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
context "readonly" do
|
16
|
-
before do
|
17
|
-
@bus.pub_redis.slaveof "127.0.0.80", "666"
|
18
|
-
end
|
19
16
|
|
20
17
|
after do
|
21
18
|
@bus.pub_redis.slaveof "no", "one"
|
22
19
|
end
|
23
20
|
|
24
21
|
it "should be able to store messages in memory for a period while in read only" do
|
22
|
+
|
23
|
+
skip "This spec changes redis behavior that in turn means other specs run slow"
|
24
|
+
|
25
|
+
@bus.pub_redis.slaveof "127.0.0.80", "666"
|
25
26
|
@bus.max_in_memory_publish_backlog = 2
|
26
27
|
|
27
28
|
3.times do
|
@@ -33,35 +33,19 @@ describe MessageBus::TimerThread do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it "queues jobs in the correct order" do
|
36
|
-
counter = 0
|
37
|
-
failed = nil
|
38
36
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
# threading introduces a delay meaning we need to wait a long time
|
44
|
-
Thread.new do
|
45
|
-
ready += 1
|
46
|
-
while ready < 4
|
47
|
-
sleep 0
|
48
|
-
end
|
49
|
-
# on my mbp I measure at least 200ms of schedule jitter for Thread
|
50
|
-
@timer.queue(i/3.0) do
|
51
|
-
#puts "counter #{counter} i #{i}"
|
52
|
-
failed = true if counter != i
|
53
|
-
counter += 1
|
54
|
-
end
|
55
|
-
#puts "\nqueued #{i/200.0} #{i} #{Time.now.to_f}\n"
|
37
|
+
results = []
|
38
|
+
(0..3).to_a.reverse.each do |i|
|
39
|
+
@timer.queue(0.005 * i) do
|
40
|
+
results << i
|
56
41
|
end
|
57
42
|
end
|
58
43
|
|
59
44
|
wait_for(3000) {
|
60
|
-
|
45
|
+
4 == results.length
|
61
46
|
}
|
62
47
|
|
63
|
-
|
64
|
-
failed.should == nil
|
48
|
+
results.should == [0,1,2,3]
|
65
49
|
end
|
66
50
|
|
67
51
|
it "should call the error callback if something goes wrong" do
|
data/spec/spec_helper.rb
CHANGED
@@ -11,7 +11,12 @@ RSpec.configure do |config|
|
|
11
11
|
|
12
12
|
# to debug hanging tests
|
13
13
|
# config.before :each do |x|
|
14
|
-
#
|
14
|
+
# $start = Time.now
|
15
|
+
# puts "Start: #{x.metadata[:location]}"
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# config.after :each do |x|
|
19
|
+
# puts "#{x.metadata[:location]} #{Time.now - $start}"
|
15
20
|
# end
|
16
21
|
end
|
17
22
|
|
@@ -1,12 +1,6 @@
|
|
1
1
|
/*jshint bitwise: false*/
|
2
|
+
"use strict;"
|
2
3
|
|
3
|
-
/**
|
4
|
-
Message Bus functionality.
|
5
|
-
|
6
|
-
@class MessageBus
|
7
|
-
@namespace Discourse
|
8
|
-
@module Discourse
|
9
|
-
**/
|
10
4
|
window.MessageBus = (function() {
|
11
5
|
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
|
12
6
|
var callbacks, clientId, failCount, shouldLongPoll, queue, responseCallbacks, uniqueId, baseUrl;
|
@@ -30,12 +24,13 @@ window.MessageBus = (function() {
|
|
30
24
|
baseUrl = "/";
|
31
25
|
paused = false;
|
32
26
|
later = [];
|
27
|
+
chunkedBackoff = 0;
|
33
28
|
|
34
29
|
var hiddenProperty;
|
35
30
|
|
36
31
|
|
37
32
|
(function(){
|
38
|
-
var prefixes = ["","webkit","ms","moz"
|
33
|
+
var prefixes = ["","webkit","ms","moz"];
|
39
34
|
for(var i=0; i<prefixes.length; i++) {
|
40
35
|
var prefix = prefixes[i];
|
41
36
|
var check = prefix + (prefix === "" ? "hidden" : "Hidden");
|
@@ -53,6 +48,11 @@ window.MessageBus = (function() {
|
|
53
48
|
}
|
54
49
|
};
|
55
50
|
|
51
|
+
var hasonprogress = (new XMLHttpRequest()).onprogress === null;
|
52
|
+
var allowChunked = function(){
|
53
|
+
return me.enableChunkedEncoding && hasonprogress;
|
54
|
+
};
|
55
|
+
|
56
56
|
shouldLongPoll = function() {
|
57
57
|
return me.alwaysLongPoll || !isHidden();
|
58
58
|
};
|
@@ -65,7 +65,6 @@ window.MessageBus = (function() {
|
|
65
65
|
var gotData = false;
|
66
66
|
if (!messages) return false; // server unexpectedly closed connection
|
67
67
|
|
68
|
-
|
69
68
|
for (var i=0; i<messages.length; i++) {
|
70
69
|
var message = messages[i];
|
71
70
|
gotData = true;
|
@@ -93,6 +92,20 @@ window.MessageBus = (function() {
|
|
93
92
|
return gotData;
|
94
93
|
};
|
95
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
|
+
|
96
109
|
longPoller = function(poll,data){
|
97
110
|
var gotData = false;
|
98
111
|
var aborted = false;
|
@@ -100,27 +113,97 @@ window.MessageBus = (function() {
|
|
100
113
|
totalAjaxCalls += 1;
|
101
114
|
data.__seq = totalAjaxCalls;
|
102
115
|
|
103
|
-
|
104
|
-
|
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
|
+
|
127
|
+
if (!chunked){
|
128
|
+
headers["Dont-Chunk"] = 'true';
|
129
|
+
}
|
130
|
+
|
131
|
+
var dataType = chunked ? "text" : "json";
|
132
|
+
|
133
|
+
var handle_progress = function(payload, position) {
|
134
|
+
|
135
|
+
var separator = "\r\n|\r\n";
|
136
|
+
var endChunk = payload.indexOf(separator, position);
|
137
|
+
|
138
|
+
if (endChunk === -1) {
|
139
|
+
return position;
|
140
|
+
}
|
141
|
+
|
142
|
+
var chunk = payload.substring(position, endChunk);
|
143
|
+
chunk = chunk.replace(/\r\n\|\|\r\n/g, separator);
|
144
|
+
|
145
|
+
try {
|
146
|
+
console.log(chunk);
|
147
|
+
reqSuccess(JSON.parse(chunk));
|
148
|
+
} catch(e) {
|
149
|
+
if (console.log) {
|
150
|
+
console.log("FAILED TO PARSE CHUNKED REPLY");
|
151
|
+
console.log(data);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
|
155
|
+
return handle_progress(payload, endChunk + separator.length);
|
156
|
+
}
|
157
|
+
|
158
|
+
var disableChunked = function(){
|
159
|
+
if (me.longPoll) {
|
160
|
+
me.longPoll.abort();
|
161
|
+
chunkedBackoff = 30;
|
162
|
+
}
|
163
|
+
};
|
164
|
+
|
165
|
+
var req = me.ajax({
|
166
|
+
url: me.baseUrl + "message-bus/" + me.clientId + "/poll?" + (!longPoll ? "dlp=t" : ""),
|
105
167
|
data: data,
|
106
168
|
cache: false,
|
107
|
-
dataType:
|
169
|
+
dataType: dataType,
|
108
170
|
type: 'POST',
|
109
|
-
headers:
|
110
|
-
|
171
|
+
headers: headers,
|
172
|
+
xhr: function() {
|
173
|
+
var xhr = jQuery.ajaxSettings.xhr();
|
174
|
+
|
175
|
+
if (!chunked) {
|
176
|
+
return xhr;
|
177
|
+
}
|
178
|
+
|
179
|
+
var position = 0;
|
180
|
+
|
181
|
+
// if it takes longer than 3000 ms to get first chunk, we have some proxy
|
182
|
+
// this is messing with us, so just backoff from using chunked for now
|
183
|
+
var chunkedTimeout = setTimeout(disableChunked,3000);
|
184
|
+
|
185
|
+
xhr.onprogress = function () {
|
186
|
+
clearTimeout(chunkedTimeout);
|
187
|
+
|
188
|
+
if(xhr.getResponseHeader('Content-Type') === 'application/json; charset=utf-8') {
|
189
|
+
// not chunked we are sending json back
|
190
|
+
chunked = false;
|
191
|
+
return;
|
192
|
+
}
|
193
|
+
position = handle_progress(xhr.responseText, position);
|
194
|
+
}
|
195
|
+
|
196
|
+
return xhr;
|
111
197
|
},
|
112
198
|
success: function(messages) {
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
gotData = processMessages(messages);
|
122
|
-
}
|
123
|
-
},
|
199
|
+
if (!chunked) {
|
200
|
+
// we may have requested text so jQuery will not parse
|
201
|
+
if (typeof(messages) === "string") {
|
202
|
+
messages = JSON.parse(messages);
|
203
|
+
}
|
204
|
+
gotData = reqSuccess(messages);
|
205
|
+
}
|
206
|
+
},
|
124
207
|
error: function(xhr, textStatus, err) {
|
125
208
|
if(textStatus === "abort") {
|
126
209
|
aborted = true;
|
@@ -161,9 +244,12 @@ window.MessageBus = (function() {
|
|
161
244
|
me.longPoll = null;
|
162
245
|
}
|
163
246
|
});
|
247
|
+
|
248
|
+
return req;
|
164
249
|
};
|
165
250
|
|
166
251
|
me = {
|
252
|
+
enableChunkedEncoding: true,
|
167
253
|
enableLongPolling: true,
|
168
254
|
callbackInterval: 15000,
|
169
255
|
backgroundCallbackInterval: 60000,
|
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:
|
4
|
+
version: 2.0.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -76,7 +76,6 @@ files:
|
|
76
76
|
- lib/message_bus/diagnostics.rb
|
77
77
|
- lib/message_bus/em_ext.rb
|
78
78
|
- lib/message_bus/message.rb
|
79
|
-
- lib/message_bus/message_handler.rb
|
80
79
|
- lib/message_bus/rack/diagnostics.rb
|
81
80
|
- lib/message_bus/rack/middleware.rb
|
82
81
|
- lib/message_bus/rack/thin_ext.rb
|
@@ -85,17 +84,15 @@ files:
|
|
85
84
|
- lib/message_bus/timer_thread.rb
|
86
85
|
- lib/message_bus/version.rb
|
87
86
|
- message_bus.gemspec
|
88
|
-
- spec/lib/assets/asset_encoding_spec.rb
|
89
|
-
- spec/lib/client_spec.rb
|
90
|
-
- spec/lib/connection_manager_spec.rb
|
91
87
|
- spec/lib/fake_async_middleware.rb
|
92
|
-
- spec/lib/
|
88
|
+
- spec/lib/message_bus/assets/asset_encoding_spec.rb
|
89
|
+
- spec/lib/message_bus/client_spec.rb
|
90
|
+
- spec/lib/message_bus/connection_manager_spec.rb
|
91
|
+
- spec/lib/message_bus/multi_process_spec.rb
|
92
|
+
- spec/lib/message_bus/rack/middleware_spec.rb
|
93
|
+
- spec/lib/message_bus/redis/reliable_pub_sub_spec.rb
|
94
|
+
- spec/lib/message_bus/timer_thread_spec.rb
|
93
95
|
- spec/lib/message_bus_spec.rb
|
94
|
-
- spec/lib/message_handler_spec.rb
|
95
|
-
- spec/lib/middleware_spec.rb
|
96
|
-
- spec/lib/multi_process_spec.rb
|
97
|
-
- spec/lib/redis/reliable_pub_sub_spec.rb
|
98
|
-
- spec/lib/timer_thread_spec.rb
|
99
96
|
- spec/spec_helper.rb
|
100
97
|
- vendor/assets/javascripts/message-bus.js
|
101
98
|
homepage: https://github.com/SamSaffron/message_bus
|
@@ -113,25 +110,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
110
|
version: '0'
|
114
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
112
|
requirements:
|
116
|
-
- - "
|
113
|
+
- - ">"
|
117
114
|
- !ruby/object:Gem::Version
|
118
|
-
version:
|
115
|
+
version: 1.3.1
|
119
116
|
requirements: []
|
120
117
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.4.5
|
118
|
+
rubygems_version: 2.4.5
|
122
119
|
signing_key:
|
123
120
|
specification_version: 4
|
124
121
|
summary: ''
|
125
122
|
test_files:
|
126
|
-
- spec/lib/assets/asset_encoding_spec.rb
|
127
|
-
- spec/lib/client_spec.rb
|
128
|
-
- spec/lib/connection_manager_spec.rb
|
129
123
|
- spec/lib/fake_async_middleware.rb
|
130
|
-
- spec/lib/
|
124
|
+
- spec/lib/message_bus/assets/asset_encoding_spec.rb
|
125
|
+
- spec/lib/message_bus/client_spec.rb
|
126
|
+
- spec/lib/message_bus/connection_manager_spec.rb
|
127
|
+
- spec/lib/message_bus/multi_process_spec.rb
|
128
|
+
- spec/lib/message_bus/rack/middleware_spec.rb
|
129
|
+
- spec/lib/message_bus/redis/reliable_pub_sub_spec.rb
|
130
|
+
- spec/lib/message_bus/timer_thread_spec.rb
|
131
131
|
- spec/lib/message_bus_spec.rb
|
132
|
-
- spec/lib/message_handler_spec.rb
|
133
|
-
- spec/lib/middleware_spec.rb
|
134
|
-
- spec/lib/multi_process_spec.rb
|
135
|
-
- spec/lib/redis/reliable_pub_sub_spec.rb
|
136
|
-
- spec/lib/timer_thread_spec.rb
|
137
132
|
- spec/spec_helper.rb
|