message_bus 2.0.0.beta.6 → 2.0.0.beta.7

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 686569cf588c00aa211a970eab14d37cf979c844
4
- data.tar.gz: 167ad799942ea8f8de1e945015bae4f687c4629f
3
+ metadata.gz: 765d5f2c439f0bcc0ca030a838d93510ed638916
4
+ data.tar.gz: 23a0428b2f62625e4063c066828d9fb5925a0a86
5
5
  SHA512:
6
- metadata.gz: 6810d52979d00f065b8de475f8cbeb81edbe7ae8fc706d1a818d32ac2f1c36f2f9ee94c3585968beba594dde53064f82a58348c0948a2b0d64326e356880cb32
7
- data.tar.gz: 0bd9ac5196a77f53797e834b3e296bdad9328fcc6a28331b5e53456527eb5be8df25de76fd3aa05e960f4927531d19f7bfb8ffafdb163006bb1264273d0987d1
6
+ metadata.gz: 19127a42396bebe0d047fc7a3c41d7be908072711ef294e71d4f6546acd260b93520a4d0eb391d39b63253b5d6e057ee43aebaf7e032dd8f6cc6531352131001
7
+ data.tar.gz: e863e48441974a73d3f956b9ba2cf01622bbc173ac5db435d3b0c1d38db0dab9b2b884d230cf50ab463ec225d323a73f4a7fd0299a033940074b5aaf29bb6583
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ 26-04-2016
2
+
3
+ - Version 2.0.0.beta.7
4
+
5
+ - Feature: Support custom HTTP headers without depending on jQuery @nathanstitt
6
+ - Feature: Allow subscribe at a particular position from server side @sam
7
+
1
8
  29-02-2016
2
9
 
3
10
  - Version 2.0.0.beta.6
data/README.md CHANGED
@@ -49,6 +49,16 @@ MessageBus.subscribe "/channel" do |msg|
49
49
  # block called in a background thread when message is received
50
50
  end
51
51
 
52
+ # subscribe to channel and receive the entire backlog
53
+ MessageBus.subscribe "/channel", 0 do |msg|
54
+ # block called in a background thread when message is received
55
+ end
56
+
57
+ # subscribe to channel and receive the backlog starting at message 6
58
+ MessageBus.subscribe "/channel", 5 do |msg|
59
+ # block called in a background thread when message is received
60
+ end
61
+
52
62
  MessageBus.backlog "/channel", id
53
63
  # returns all messages after the id
54
64
 
@@ -175,7 +185,7 @@ maxPollInterval|180000|If request to the server start failing, MessageBus will b
175
185
  alwaysLongPoll|false|For debugging you may want to disable the "is browser in background" check and always long-poll
176
186
  baseUrl|/|If message bus is mounted in a subdirectory of different domain, you may configure it to perform requests there
177
187
  ajax|$.ajax or XMLHttpRequest|MessageBus will first attempt to use jQuery and then fallback to a plain XMLHttpRequest version that's contained in the `messsage-bus-ajax.js` file. `messsage-bus-ajax.js` must be loaded after `messsage-bus.js` for it to be used.
178
-
188
+ headers|{}|Extra headers to be include with request. Properties and values of object must be valid values for HTTP Headers, i.e. no spaces and control characters.
179
189
  **API**:
180
190
 
181
191
  `MessageBus.diagnostics()` : Returns a log that may be used for diagnostics on the status of message bus
@@ -123,6 +123,9 @@
123
123
  var headers = {
124
124
  'X-SILENCE-LOGGER': 'true'
125
125
  };
126
+ for (var name in me.headers){
127
+ headers[name] = me.headers[name];
128
+ }
126
129
 
127
130
  if (!chunked){
128
131
  headers["Dont-Chunk"] = 'true';
@@ -274,6 +277,7 @@
274
277
  clientId: clientId,
275
278
  alwaysLongPoll: false,
276
279
  baseUrl: baseUrl,
280
+ headers: {},
277
281
  ajax: (jQuery && jQuery.ajax),
278
282
  noConflict: function(){
279
283
  global.MessageBus = global.MessageBus.previousMessageBus;
@@ -121,10 +121,7 @@ class Chat < Sinatra::Base
121
121
  $(function() {
122
122
  var name;
123
123
 
124
- MessageBus.ajax = function(args){
125
- args["headers"]["X-NAME"] = name;
126
- return $.ajax(args);
127
- };
124
+ MessageBus.headers["X-NAME"] = name;
128
125
 
129
126
  var enter = function(name, opts) {
130
127
  if (opts && opts.check) {
@@ -2,6 +2,7 @@ base_image: "discourse/base:1.0.15"
2
2
 
3
3
  update_pups: false
4
4
 
5
+
5
6
  params:
6
7
  home: /var/www/message_bus
7
8
 
@@ -10,11 +11,15 @@ templates:
10
11
 
11
12
  expose:
12
13
  - "80:80"
14
+ - "443:443"
13
15
 
14
16
  volumes:
15
17
  - volume:
16
18
  host: /var/docker/shared/chat
17
19
  guest: /shared
20
+ - volume:
21
+ host: /etc/letsencrypt
22
+ guest: /etc/letsencrypt
18
23
 
19
24
  hooks:
20
25
  after_redis:
@@ -45,6 +50,10 @@ hooks:
45
50
  filename: /etc/nginx/nginx.conf
46
51
  from: pid /run/nginx.pid;
47
52
  to: daemon off;
53
+ - exec:
54
+ cmd:
55
+ - "mkdir -p /shared/ssl"
56
+ - "[ -e /shared/ssl/dhparams.pem ] || openssl dhparam -out /shared/ssl/dhparams.pem 2048"
48
57
  - file:
49
58
  path: /etc/nginx/conf.d/chat.conf
50
59
  contents: |
@@ -53,11 +62,25 @@ hooks:
53
62
  }
54
63
  server {
55
64
  listen 80;
65
+ rewrite ^ https://chat.samsaffron.com$request_uri? permanent;
66
+ }
67
+ server {
68
+ listen 443 ssl http2;
69
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
70
+ ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA;
71
+ ssl_prefer_server_ciphers on;
72
+ ssl_session_tickets off;
73
+ ssl_session_timeout 1d;
74
+ ssl_session_cache shared:SSL:1m;
75
+ ssl_dhparam /shared/ssl/dhparams.pem;
76
+ ssl_certificate /etc/letsencrypt/live/chat.samsaffron.com/fullchain.pem;
77
+ ssl_certificate_key /etc/letsencrypt/live/chat.samsaffron.com/privkey.pem;
56
78
  gzip on;
57
79
  gzip_types application/json text/css application/x-javascript;
58
80
  gzip_min_length 1000;
59
81
  server_name chat.samsaffron.com;
60
82
  keepalive_timeout 65;
83
+ root /shared/letsencrypt;
61
84
 
62
85
  location /message-bus/ {
63
86
  proxy_set_header Host $http_host;
@@ -70,7 +93,6 @@ hooks:
70
93
  break;
71
94
  }
72
95
 
73
-
74
96
  location / {
75
97
  try_files $uri @chat;
76
98
  break;
data/lib/message_bus.rb CHANGED
@@ -257,8 +257,14 @@ module MessageBus::Implementation
257
257
  channel.split(ENCODE_SITE_TOKEN)
258
258
  end
259
259
 
260
- def subscribe(channel=nil, &blk)
261
- subscribe_impl(channel, nil, &blk)
260
+ def subscribe(channel=nil, last_id=-1, &blk)
261
+ subscribe_impl(channel, nil, last_id, &blk)
262
+ end
263
+
264
+ # subscribe only on current site
265
+ def local_subscribe(channel=nil, last_id=-1, &blk)
266
+ site_id = site_id_lookup.call if site_id_lookup && ! global?(channel)
267
+ subscribe_impl(channel, site_id, last_id, &blk)
262
268
  end
263
269
 
264
270
  def unsubscribe(channel=nil, &blk)
@@ -270,12 +276,6 @@ module MessageBus::Implementation
270
276
  unsubscribe_impl(channel, site_id, &blk)
271
277
  end
272
278
 
273
- # subscribe only on current site
274
- def local_subscribe(channel=nil, &blk)
275
- site_id = site_id_lookup.call if site_id_lookup && ! global?(channel)
276
- subscribe_impl(channel, site_id, &blk)
277
- end
278
-
279
279
  def global_backlog(last_id=nil)
280
280
  backlog(nil, last_id)
281
281
  end
@@ -372,10 +372,45 @@ module MessageBus::Implementation
372
372
  msg.client_ids = parsed["client_ids"]
373
373
  end
374
374
 
375
- def subscribe_impl(channel, site_id, &blk)
375
+ def replay_backlog(channel, last_id, site_id)
376
+ id = nil
377
+
378
+ backlog(channel, last_id, site_id).each do |m|
379
+ yield m
380
+ id = m.message_id
381
+ end
382
+
383
+ id
384
+ end
385
+
386
+ def subscribe_impl(channel, site_id, last_id, &blk)
376
387
 
377
388
  raise MessageBus::BusDestroyed if @destroyed
378
389
 
390
+ if last_id >= 0
391
+ # this gets a bit tricky, but we got to ensure ordering so we wrap the block
392
+ original_blk = blk
393
+ current_id = replay_backlog(channel, last_id, site_id, &blk)
394
+ just_yield = false
395
+
396
+ # we double check to ensure no messages snuck through while we were subscribing
397
+ blk = proc do |m|
398
+ if just_yield
399
+ original_blk.call m
400
+ else
401
+ if current_id && current_id == (m.message_id-1)
402
+ original_blk.call m
403
+ just_yield = true
404
+ else
405
+ current_id = replay_backlog(channel, current_id, site_id, &original_blk)
406
+ if (current_id == m.id)
407
+ just_yield = true
408
+ end
409
+ end
410
+ end
411
+ end
412
+ end
413
+
379
414
  @subscriptions ||= {}
380
415
  @subscriptions[site_id] ||= {}
381
416
  @subscriptions[site_id][channel] ||= []
@@ -52,11 +52,11 @@ class MessageBus::Postgres::Client
52
52
  end
53
53
 
54
54
  def backlog(channel, backlog_id)
55
- hold{|conn| exec_prepared(conn, 'channel_backlog', [channel, backlog_id]){|r| r.values.each{|a| a[0] = a[0].to_i}}}
55
+ hold{|conn| exec_prepared(conn, 'channel_backlog', [channel, backlog_id]){|r| r.values.each{|a| a[0] = a[0].to_i}}} || []
56
56
  end
57
57
 
58
58
  def global_backlog(backlog_id)
59
- hold{|conn| exec_prepared(conn, 'global_backlog', [backlog_id]){|r| r.values.each{|a| a[0] = a[0].to_i}}}
59
+ hold{|conn| exec_prepared(conn, 'global_backlog', [backlog_id]){|r| r.values.each{|a| a[0] = a[0].to_i}}} || []
60
60
  end
61
61
 
62
62
  def get_value(channel, id)
@@ -157,7 +157,7 @@ class MessageBus::Postgres::Client
157
157
  conn = sync{@available.shift} || new_pg_connection
158
158
  sync{@allocated[Thread.current] = conn}
159
159
  yield conn
160
- rescue PG::ConnectionBad => e
160
+ rescue PG::ConnectionBad, PG::UnableToSend => e
161
161
  # don't add this connection back to the pool
162
162
  ensure
163
163
  sync{@allocated.delete(Thread.current)}
@@ -279,8 +279,6 @@ class MessageBus::Postgres::ReliablePubSub
279
279
  end
280
280
 
281
281
  def global_backlog(last_id = nil)
282
- last_id = last_id.to_i
283
-
284
282
  items = client.global_backlog last_id.to_i
285
283
 
286
284
  items.map! do |id, channel, data|
@@ -1,3 +1,3 @@
1
1
  module MessageBus
2
- VERSION = "2.0.0.beta.6"
2
+ VERSION = "2.0.0.beta.7"
3
3
  end
@@ -24,7 +24,9 @@ var encodeChunks = function(xhr, chunks) {
24
24
  beforeEach(function () {
25
25
  var spec = this;
26
26
 
27
- function MockedXMLHttpRequest(options){ this.options = options; }
27
+ function MockedXMLHttpRequest(){
28
+ this.headers = {};
29
+ };
28
30
  MockedXMLHttpRequest.prototype.send = function(){
29
31
  this.readyState = 4
30
32
  this.responseText = encodeChunks(this, spec.responseChunks);
@@ -35,7 +37,9 @@ beforeEach(function () {
35
37
  }
36
38
  MockedXMLHttpRequest.prototype.open = function(){ }
37
39
  MockedXMLHttpRequest.prototype.abort = function(){ }
38
- MockedXMLHttpRequest.prototype.setRequestHeader = function(){ }
40
+ MockedXMLHttpRequest.prototype.setRequestHeader = function(k,v){
41
+ this.headers[k] = v;
42
+ }
39
43
  MockedXMLHttpRequest.prototype.getResponseHeader = function(){
40
44
  return 'text/plain; charset=utf-8';
41
45
  }
@@ -74,4 +74,17 @@ describe("Messagebus", function() {
74
74
  window.MessageBus = mb;
75
75
  });
76
76
 
77
+ testMB('sends using custom header', function(){
78
+ MessageBus.headers['X-MB-TEST-VALUE'] = '42';
79
+ this.perform(function(message, xhr){
80
+ expect(xhr.headers).toEqual({
81
+ 'X-SILENCE-LOGGER': 'true',
82
+ 'X-MB-TEST-VALUE': '42',
83
+ 'Content-Type': 'application/json'
84
+ });
85
+ }).finally(function(){
86
+ MessageBus.headers = {};
87
+ })
88
+ });
89
+
77
90
  });
@@ -18,6 +18,28 @@ describe MessageBus do
18
18
  @bus.destroy
19
19
  end
20
20
 
21
+ it "can subscribe from a point in time" do
22
+ @bus.publish("/minion", "banana")
23
+
24
+ data1 = []
25
+ data2 = []
26
+
27
+ @bus.subscribe("/minion") do |msg|
28
+ data1 << msg.data
29
+ end
30
+
31
+ @bus.subscribe("/minion", 0) do |msg|
32
+ data2 << msg.data
33
+ end
34
+
35
+ @bus.publish("/minion", "bananana")
36
+
37
+ wait_for(2000){ data2.length == 2 && data1.length == 1}
38
+
39
+ data1.must_equal ['bananana']
40
+ data2.must_equal ['banana', 'bananana']
41
+ end
42
+
21
43
  it "can transmit client_ids" do
22
44
  client_ids = nil
23
45
 
@@ -0,0 +1,44 @@
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);
@@ -123,6 +123,9 @@
123
123
  var headers = {
124
124
  'X-SILENCE-LOGGER': 'true'
125
125
  };
126
+ for (var name in me.headers){
127
+ headers[name] = me.headers[name];
128
+ }
126
129
 
127
130
  if (!chunked){
128
131
  headers["Dont-Chunk"] = 'true';
@@ -274,6 +277,7 @@
274
277
  clientId: clientId,
275
278
  alwaysLongPoll: false,
276
279
  baseUrl: baseUrl,
280
+ headers: {},
277
281
  ajax: (jQuery && jQuery.ajax),
278
282
  noConflict: function(){
279
283
  global.MessageBus = global.MessageBus.previousMessageBus;
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.6
4
+ version: 2.0.0.beta.7
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-03-31 00:00:00.000000000 Z
11
+ date: 2016-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -131,6 +131,7 @@ files:
131
131
  - spec/lib/message_bus/timer_thread_spec.rb
132
132
  - spec/lib/message_bus_spec.rb
133
133
  - spec/spec_helper.rb
134
+ - vendor/assets/javascripts/message-bus-ajax.js
134
135
  - vendor/assets/javascripts/message-bus.js
135
136
  homepage: https://github.com/SamSaffron/message_bus
136
137
  licenses: