message_bus 1.1.1 → 2.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of message_bus might be problematic. Click here for more details.

@@ -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
- (Time.now.to_f * 1000 - s).should < 30
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
- ready = 0
40
-
41
- items = (0...4).to_a.shuffle
42
- items.map do |i|
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
- counter == items.length
45
+ 4 == results.length
61
46
  }
62
47
 
63
- counter.should == items.length
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
- # p x.metadata[:location]
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","ms"];
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
- return me.ajax({
104
- url: me.baseUrl + "message-bus/" + me.clientId + "/poll?" + (!shouldLongPoll() || !me.enableLongPolling ? "dlp=t" : ""),
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: 'json',
169
+ dataType: dataType,
108
170
  type: 'POST',
109
- headers: {
110
- 'X-SILENCE-LOGGER': 'true'
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
- failCount = 0;
114
- if (paused) {
115
- if (messages) {
116
- for (var i=0; i<messages.length; i++) {
117
- later.push(messages[i]);
118
- }
119
- }
120
- } else {
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: 1.1.1
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: 2015-12-09 00:00:00.000000000 Z
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/handlers/demo_message_handler.rb
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: '0'
115
+ version: 1.3.1
119
116
  requirements: []
120
117
  rubyforge_project:
121
- rubygems_version: 2.4.5.1
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/handlers/demo_message_handler.rb
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