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

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 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: