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 +4 -4
- data/CHANGELOG +7 -0
- data/README.md +11 -1
- data/assets/message-bus.js +4 -0
- data/examples/chat/chat.rb +1 -4
- data/examples/chat/docker_container/chat.yml +23 -1
- data/lib/message_bus.rb +44 -9
- data/lib/message_bus/backends/postgres.rb +3 -5
- data/lib/message_bus/version.rb +1 -1
- data/spec/assets/SpecHelper.js +6 -2
- data/spec/assets/message-bus.spec.js +13 -0
- data/spec/lib/message_bus_spec.rb +22 -0
- data/vendor/assets/javascripts/message-bus-ajax.js +44 -0
- data/vendor/assets/javascripts/message-bus.js +4 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 765d5f2c439f0bcc0ca030a838d93510ed638916
|
4
|
+
data.tar.gz: 23a0428b2f62625e4063c066828d9fb5925a0a86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19127a42396bebe0d047fc7a3c41d7be908072711ef294e71d4f6546acd260b93520a4d0eb391d39b63253b5d6e057ee43aebaf7e032dd8f6cc6531352131001
|
7
|
+
data.tar.gz: e863e48441974a73d3f956b9ba2cf01622bbc173ac5db435d3b0c1d38db0dab9b2b884d230cf50ab463ec225d323a73f4a7fd0299a033940074b5aaf29bb6583
|
data/CHANGELOG
CHANGED
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
|
data/assets/message-bus.js
CHANGED
@@ -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;
|
data/examples/chat/chat.rb
CHANGED
@@ -121,10 +121,7 @@ class Chat < Sinatra::Base
|
|
121
121
|
$(function() {
|
122
122
|
var name;
|
123
123
|
|
124
|
-
MessageBus.
|
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
|
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|
|
data/lib/message_bus/version.rb
CHANGED
data/spec/assets/SpecHelper.js
CHANGED
@@ -24,7 +24,9 @@ var encodeChunks = function(xhr, chunks) {
|
|
24
24
|
beforeEach(function () {
|
25
25
|
var spec = this;
|
26
26
|
|
27
|
-
function MockedXMLHttpRequest(
|
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.
|
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-
|
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:
|