message_bus 2.0.0.beta.2 → 2.0.0.beta.3
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/.travis.yml +10 -2
- data/CHANGELOG +10 -0
- data/Gemfile +1 -6
- data/README.md +43 -16
- data/Rakefile +18 -4
- data/lib/message_bus.rb +64 -47
- data/lib/message_bus/backends/postgres.rb +396 -0
- data/lib/message_bus/{redis/reliable_pub_sub.rb → backends/redis.rb} +1 -0
- data/lib/message_bus/rack/middleware.rb +14 -5
- data/lib/message_bus/version.rb +1 -1
- data/message_bus.gemspec +3 -1
- data/spec/lib/message_bus/assets/asset_encoding_spec.rb +4 -4
- data/spec/lib/message_bus/backends/postgres_spec.rb +208 -0
- data/spec/lib/message_bus/{redis/reliable_pub_sub_spec.rb → backends/redis_spec.rb} +25 -23
- data/spec/lib/message_bus/client_spec.rb +28 -27
- data/spec/lib/message_bus/connection_manager_spec.rb +22 -24
- data/spec/lib/message_bus/multi_process_spec.rb +54 -27
- data/spec/lib/message_bus/rack/middleware_spec.rb +81 -38
- data/spec/lib/message_bus/timer_thread_spec.rb +6 -6
- data/spec/lib/message_bus_spec.rb +36 -35
- data/spec/spec_helper.rb +16 -21
- metadata +24 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13a3191447206ef44053ab24b6ae199b7e18d11e
|
4
|
+
data.tar.gz: 2b5037efdc6052aec3e6087461b26d5902ea0971
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a3d536e64f1efd37eec538cbef41b794a083cb9516d4457b26d0c2b4d24af886162720a46896951e6921333be15abce7c573898ac0b277a38f90681b1612a1e
|
7
|
+
data.tar.gz: 9aabc10913a3816708fc808893d98cfea290940af41b0ab19478633db2abfcdc2091df8c8140c3fdfc9f82ea3e7f27970688c0310536003bb259dd3c3db7e14c
|
data/.travis.yml
CHANGED
@@ -3,9 +3,17 @@ language: ruby
|
|
3
3
|
rvm:
|
4
4
|
- 1.9.3
|
5
5
|
- 2.0.0
|
6
|
-
- 2.1.
|
7
|
-
- 2.2
|
6
|
+
- 2.1.8
|
7
|
+
- 2.2.4
|
8
|
+
- 2.3.0
|
8
9
|
gemfile:
|
9
10
|
- Gemfile
|
11
|
+
addons:
|
12
|
+
postgresql: "9.4"
|
13
|
+
env:
|
14
|
+
- PGUSER=postgres
|
15
|
+
before_script:
|
16
|
+
- psql -c 'create database message_bus_test;' -U postgres
|
10
17
|
services:
|
11
18
|
- redis-server
|
19
|
+
- postgresql
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
29-02-2016
|
2
|
+
|
3
|
+
- Version 2.0.0.beta.3
|
4
|
+
|
5
|
+
- Feature: Postgresql backend @jeremyevans
|
6
|
+
- Breaking Change: Configuration API changed see Readme for details @jeremyevans
|
7
|
+
- Breaking Change: Remove runtime dependency on Redis @jeremyevans
|
8
|
+
- Dev: Convert all specs to minitest @jeremyevans
|
9
|
+
- Feature: Support passing channels to Rack middleware via env['message_bus.channels'] via @jeremyevans
|
10
|
+
|
1
11
|
03-01-2016
|
2
12
|
|
3
13
|
- Version 2.0.0.beta.2
|
data/Gemfile
CHANGED
@@ -4,13 +4,8 @@ source 'https://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
group :test do
|
7
|
-
gem '
|
8
|
-
gem 'redis'
|
7
|
+
gem 'minitest'
|
9
8
|
gem 'rake'
|
10
|
-
gem 'rbtrace'
|
11
|
-
gem 'guard-rspec'
|
12
|
-
gem 'rb-inotify', require: RUBY_PLATFORM =~ /linux/i ? 'rb-inotify' : false
|
13
|
-
gem 'rack'
|
14
9
|
gem 'http_parser.rb'
|
15
10
|
gem 'thin'
|
16
11
|
gem 'rack-test', require: 'rack/test'
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# MessageBus
|
2
2
|
|
3
|
-
A reliable, robust messaging bus for Ruby processes and web clients
|
3
|
+
A reliable, robust messaging bus for Ruby processes and web clients.
|
4
4
|
|
5
5
|
MessageBus implements a Server to Server channel based protocol and Server to Web Client protocol (using polling, long-polling or long-polling + streaming)
|
6
6
|
|
@@ -49,21 +49,21 @@ MessageBus.backlog "/channel", id
|
|
49
49
|
# returns all messages after the id
|
50
50
|
|
51
51
|
# messages can be targetted at particular users or groups
|
52
|
-
MessageBus.publish "/channel", user_ids: [1,2,3], group_ids: [4,5,6]
|
52
|
+
MessageBus.publish "/channel", "hello", user_ids: [1,2,3], group_ids: [4,5,6]
|
53
53
|
|
54
54
|
# messages can be targetted at particular clients (using MessageBus.clientId)
|
55
|
-
MessageBus.publish "/channel", client_ids: ["XXX","YYY"]
|
55
|
+
MessageBus.publish "/channel", "hello", client_ids: ["XXX","YYY"]
|
56
56
|
|
57
57
|
# message bus determines the user ids and groups based on env
|
58
58
|
|
59
|
-
MessageBus.user_id_lookup do |env|
|
59
|
+
MessageBus.configure(user_id_lookup: proc do |env|
|
60
60
|
# return the user id here
|
61
|
-
end
|
61
|
+
end)
|
62
62
|
|
63
|
-
MessageBus.group_ids_lookup do |env|
|
63
|
+
MessageBus.configure(group_ids_lookup: proc do |env|
|
64
64
|
# return the group ids the user belongs to
|
65
65
|
# can be nil or []
|
66
|
-
end
|
66
|
+
end)
|
67
67
|
```
|
68
68
|
|
69
69
|
### Transport
|
@@ -100,7 +100,7 @@ MessageBus.enableChunkedEncoding = false; // in your JavaScript
|
|
100
100
|
Or
|
101
101
|
|
102
102
|
```
|
103
|
-
MessageBus.chunked_encoding_enabled
|
103
|
+
MessageBus.configure(chunked_encoding_enabled: false) // in Ruby
|
104
104
|
```
|
105
105
|
|
106
106
|
Long Polling requires no special setup, as soon as new data arrives on the channel the server delivers the data and closes the connection.
|
@@ -113,9 +113,9 @@ MessageBus can be used in an environment that hosts multiple sites by multiplexi
|
|
113
113
|
|
114
114
|
```ruby
|
115
115
|
# define a site_id lookup method
|
116
|
-
MessageBus.site_id_lookup do
|
116
|
+
MessageBus.configure(site_id_lookup: proc do
|
117
117
|
some_method_that_returns_site_id_string
|
118
|
-
end
|
118
|
+
end)
|
119
119
|
|
120
120
|
# you may post messages just to this site
|
121
121
|
MessageBus.publish "/channel", "some message"
|
@@ -137,6 +137,11 @@ JavaScript can listen on any channel (and receive notification via polling or lo
|
|
137
137
|
```
|
138
138
|
Note, the message-bus.js file is located in the assets folder.
|
139
139
|
|
140
|
+
**Rails**
|
141
|
+
```javascript
|
142
|
+
//= require message-bus
|
143
|
+
```
|
144
|
+
|
140
145
|
```javascript
|
141
146
|
MessageBus.start(); // call once at startup
|
142
147
|
|
@@ -148,6 +153,10 @@ MessageBus.subscribe("/channel", function(data){
|
|
148
153
|
|
149
154
|
```
|
150
155
|
|
156
|
+
There is also a Ruby implementation of the client library, at
|
157
|
+
[message_bus-client](https://github.com/lowjoel/message_bus-client) with the API very similar to
|
158
|
+
that of the JavaScript client.
|
159
|
+
|
151
160
|
**Client settings**:
|
152
161
|
|
153
162
|
|
@@ -179,6 +188,13 @@ ajax|$.ajax|The only dependency on jQuery, you may set up a custom ajax function
|
|
179
188
|
|
180
189
|
`MessageBus.unsubscribe(channel,func)` : Unsubscribe callback from a particular channel
|
181
190
|
|
191
|
+
## Running tests
|
192
|
+
|
193
|
+
To run tests you need both Postgres and Redis installed. By default we will connect to the database `message_bus_test` with the current username. If you wish to override this:
|
194
|
+
|
195
|
+
```
|
196
|
+
PGUSER=some_user PGDATABASE=some_db bundle exec rake
|
197
|
+
```
|
182
198
|
|
183
199
|
|
184
200
|
## Configuration
|
@@ -188,13 +204,23 @@ ajax|$.ajax|The only dependency on jQuery, you may set up a custom ajax function
|
|
188
204
|
You can configure redis setting in `config/initializers/message_bus.rb`, like
|
189
205
|
|
190
206
|
```ruby
|
191
|
-
MessageBus.
|
207
|
+
MessageBus.configure(backend: :redis, url: "redis://:p4ssw0rd@10.0.1.1:6380/15")
|
192
208
|
```
|
193
209
|
The redis client message_bus uses is [redis-rb](https://github.com/redis/redis-rb), so you can visit it's repo to see what options you can configure.
|
194
210
|
|
211
|
+
### PostgreSQL
|
212
|
+
|
213
|
+
message_bus also supports PostgreSQL as the backend:
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
MessageBus.configure(backend: :postgres, backend_options: {user: 'message_bus', dbname: 'message_bus'})
|
217
|
+
```
|
218
|
+
|
219
|
+
The PostgreSQL client message_bus uses is [ruby-pg](https://bitbucket.org/ged/ruby-pg), so you can visit it's repo to see what options you can configure.
|
220
|
+
|
195
221
|
### Forking/threading app servers
|
196
222
|
|
197
|
-
If you're using a forking or threading app server and you're not getting immediate updates from published messages, you might need to reconnect Redis in your app server config:
|
223
|
+
If you're using a forking or threading app server and you're not getting immediate updates from published messages, you might need to reconnect Redis/PostgreSQL in your app server config:
|
198
224
|
|
199
225
|
#### Passenger
|
200
226
|
```ruby
|
@@ -229,14 +255,15 @@ after_fork do |server, worker|
|
|
229
255
|
end
|
230
256
|
```
|
231
257
|
|
258
|
+
###
|
259
|
+
|
232
260
|
## Want to help?
|
233
261
|
|
234
262
|
If you are looking to contribute to this project here are some ideas
|
235
263
|
|
236
|
-
- Build
|
237
|
-
-
|
238
|
-
- Improve general documentation
|
239
|
-
- Port the test suite to MiniTest
|
264
|
+
- Build backends for other providers (zeromq, rabbitmq, disque)
|
265
|
+
- Improve and properly document admin dashboard (add opt-in stats, better diagnostics into queues)
|
266
|
+
- Improve general documentation (Add examples, refine existing examples)
|
240
267
|
- Make MessageBus a nice website
|
241
268
|
|
242
269
|
|
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'rake/testtask'
|
2
3
|
require 'bundler'
|
3
4
|
require 'bundler/gem_tasks'
|
4
5
|
require 'bundler/setup'
|
@@ -7,8 +8,21 @@ Bundler.require(:default, :test)
|
|
7
8
|
|
8
9
|
task :default => [:spec]
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
run_spec = proc do |backend|
|
12
|
+
begin
|
13
|
+
ENV['MESSAGE_BUS_BACKEND'] = backend
|
14
|
+
sh "#{FileUtils::RUBY} -e \"ARGV.each{|f| load f}\" #{Dir['spec/**/*_spec.rb'].to_a.join(' ')}"
|
15
|
+
ensure
|
16
|
+
ENV.delete('MESSAGE_BUS_BACKEND')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
task :spec => [:spec_redis, :spec_postgres]
|
21
|
+
|
22
|
+
task :spec_redis do
|
23
|
+
run_spec.call('redis')
|
24
|
+
end
|
25
|
+
|
26
|
+
task :spec_postgres do
|
27
|
+
run_spec.call('postgres')
|
14
28
|
end
|
data/lib/message_bus.rb
CHANGED
@@ -7,7 +7,6 @@ require "message_bus/connection_manager"
|
|
7
7
|
require "message_bus/diagnostics"
|
8
8
|
require "message_bus/rack/middleware"
|
9
9
|
require "message_bus/rack/diagnostics"
|
10
|
-
require "message_bus/redis/reliable_pub_sub"
|
11
10
|
require "message_bus/timer_thread"
|
12
11
|
|
13
12
|
# we still need to take care of the logger
|
@@ -16,10 +15,13 @@ if defined?(::Rails)
|
|
16
15
|
end
|
17
16
|
|
18
17
|
module MessageBus; end
|
18
|
+
MessageBus::BACKENDS = {}
|
19
19
|
class MessageBus::InvalidMessage < StandardError; end
|
20
20
|
class MessageBus::BusDestroyed < StandardError; end
|
21
21
|
|
22
22
|
module MessageBus::Implementation
|
23
|
+
# Configuration options hash
|
24
|
+
attr_reader :config
|
23
25
|
|
24
26
|
# Like Mutex but safe for recursive calls
|
25
27
|
class Synchronizer
|
@@ -27,87 +29,90 @@ module MessageBus::Implementation
|
|
27
29
|
end
|
28
30
|
|
29
31
|
def initialize
|
32
|
+
@config = {}
|
30
33
|
@mutex = Synchronizer.new
|
31
34
|
end
|
32
35
|
|
33
36
|
def cache_assets=(val)
|
34
|
-
|
37
|
+
configure(cache_assets: val)
|
35
38
|
end
|
36
39
|
|
37
40
|
def cache_assets
|
38
|
-
if defined? @cache_assets
|
39
|
-
@cache_assets
|
41
|
+
if defined? @config[:cache_assets]
|
42
|
+
@config[:cache_assets]
|
40
43
|
else
|
41
44
|
true
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
45
48
|
def logger=(logger)
|
46
|
-
|
49
|
+
configure(logger: logger)
|
47
50
|
end
|
48
51
|
|
49
52
|
def logger
|
50
|
-
return @logger if @logger
|
53
|
+
return @config[:logger] if @config[:logger]
|
51
54
|
require 'logger'
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
+
logger = Logger.new(STDOUT)
|
56
|
+
logger.level = Logger::INFO
|
57
|
+
configure(logger: logger)
|
58
|
+
logger
|
55
59
|
end
|
56
60
|
|
57
61
|
def chunked_encoding_enabled?
|
58
|
-
@chunked_encoding_enabled == false ? false : true
|
62
|
+
@config[:chunked_encoding_enabled] == false ? false : true
|
59
63
|
end
|
60
64
|
|
61
65
|
def chunked_encoding_enabled=(val)
|
62
|
-
|
66
|
+
configure(chunked_encoding_enabled: val)
|
63
67
|
end
|
64
68
|
|
65
69
|
def long_polling_enabled?
|
66
|
-
@long_polling_enabled == false ? false : true
|
70
|
+
@config[:long_polling_enabled] == false ? false : true
|
67
71
|
end
|
68
72
|
|
69
73
|
def long_polling_enabled=(val)
|
70
|
-
|
74
|
+
configure(long_polling_enabled: val)
|
71
75
|
end
|
72
76
|
|
73
77
|
# The number of simultanuous clients we can service
|
74
78
|
# will revert to polling if we are out of slots
|
75
79
|
def max_active_clients=(val)
|
76
|
-
|
80
|
+
configure(max_active_clients: val)
|
77
81
|
end
|
78
82
|
|
79
83
|
def max_active_clients
|
80
|
-
@max_active_clients || 1000
|
84
|
+
@config[:max_active_clients] || 1000
|
81
85
|
end
|
82
86
|
|
83
87
|
def rack_hijack_enabled?
|
84
|
-
if @rack_hijack_enabled.nil?
|
85
|
-
|
88
|
+
if @config[:rack_hijack_enabled].nil?
|
89
|
+
enable = true
|
86
90
|
|
87
91
|
# without this switch passenger will explode
|
88
92
|
# it will run out of connections after about 10
|
89
93
|
if defined? PhusionPassenger
|
90
|
-
|
94
|
+
enable = false
|
91
95
|
if PhusionPassenger.respond_to? :advertised_concurrency_level
|
92
96
|
PhusionPassenger.advertised_concurrency_level = 0
|
93
|
-
|
97
|
+
enable = true
|
94
98
|
end
|
95
99
|
end
|
100
|
+
configure(rack_hijack_enabled: enable)
|
96
101
|
end
|
97
102
|
|
98
|
-
@rack_hijack_enabled
|
103
|
+
@config[:rack_hijack_enabled]
|
99
104
|
end
|
100
105
|
|
101
106
|
def rack_hijack_enabled=(val)
|
102
|
-
|
107
|
+
configure(rack_hijack_enabled: val)
|
103
108
|
end
|
104
109
|
|
105
110
|
def long_polling_interval=(millisecs)
|
106
|
-
|
111
|
+
configure(long_polling_interval: millisecs)
|
107
112
|
end
|
108
113
|
|
109
114
|
def long_polling_interval
|
110
|
-
@long_polling_interval || 25 * 1000
|
115
|
+
@config[:long_polling_interval] || 25 * 1000
|
111
116
|
end
|
112
117
|
|
113
118
|
def off
|
@@ -118,56 +123,58 @@ module MessageBus::Implementation
|
|
118
123
|
@off = false
|
119
124
|
end
|
120
125
|
|
126
|
+
def configure(config)
|
127
|
+
@config.merge!(config)
|
128
|
+
end
|
129
|
+
|
121
130
|
# Allow us to inject a redis db
|
122
131
|
def redis_config=(config)
|
123
|
-
|
132
|
+
configure(config.merge(:backend=>:redis))
|
124
133
|
end
|
125
134
|
|
126
|
-
|
127
|
-
@redis_config ||= {}
|
128
|
-
end
|
135
|
+
alias redis_config config
|
129
136
|
|
130
137
|
def site_id_lookup(&blk)
|
131
|
-
|
132
|
-
@site_id_lookup
|
138
|
+
configure(site_id_lookup: blk) if blk
|
139
|
+
@config[:site_id_lookup]
|
133
140
|
end
|
134
141
|
|
135
142
|
def user_id_lookup(&blk)
|
136
|
-
|
137
|
-
@user_id_lookup
|
143
|
+
configure(user_id_lookup: blk) if blk
|
144
|
+
@config[:user_id_lookup]
|
138
145
|
end
|
139
146
|
|
140
147
|
def group_ids_lookup(&blk)
|
141
|
-
|
142
|
-
@group_ids_lookup
|
148
|
+
configure(group_ids_lookup: blk) if blk
|
149
|
+
@config[:group_ids_lookup]
|
143
150
|
end
|
144
151
|
|
145
152
|
def is_admin_lookup(&blk)
|
146
|
-
|
147
|
-
@is_admin_lookup
|
153
|
+
configure(is_admin_lookup: blk) if blk
|
154
|
+
@config[:is_admin_lookup]
|
148
155
|
end
|
149
156
|
|
150
157
|
def extra_response_headers_lookup(&blk)
|
151
|
-
|
152
|
-
@extra_response_headers_lookup
|
158
|
+
configure(extra_response_headers_lookup: blk) if blk
|
159
|
+
@config[:extra_response_headers_lookup]
|
153
160
|
end
|
154
161
|
|
155
162
|
def on_connect(&blk)
|
156
|
-
|
157
|
-
@on_connect
|
163
|
+
configure(on_connect: blk) if blk
|
164
|
+
@config[:on_connect]
|
158
165
|
end
|
159
166
|
|
160
167
|
def on_disconnect(&blk)
|
161
|
-
|
162
|
-
@on_disconnect
|
168
|
+
configure(on_disconnect: blk) if blk
|
169
|
+
@config[:on_disconnect]
|
163
170
|
end
|
164
171
|
|
165
172
|
def allow_broadcast=(val)
|
166
|
-
|
173
|
+
configure(allow_broadcast: val)
|
167
174
|
end
|
168
175
|
|
169
176
|
def allow_broadcast?
|
170
|
-
@allow_broadcast ||=
|
177
|
+
@config[:allow_broadcast] ||=
|
171
178
|
if defined? ::Rails
|
172
179
|
::Rails.env.test? || ::Rails.env.development?
|
173
180
|
else
|
@@ -176,16 +183,24 @@ module MessageBus::Implementation
|
|
176
183
|
end
|
177
184
|
|
178
185
|
def reliable_pub_sub=(pub_sub)
|
179
|
-
|
186
|
+
configure(reliable_pub_sub: pub_sub)
|
180
187
|
end
|
181
188
|
|
182
189
|
def reliable_pub_sub
|
183
190
|
@mutex.synchronize do
|
184
191
|
return nil if @destroyed
|
185
|
-
@reliable_pub_sub ||=
|
192
|
+
@config[:reliable_pub_sub] ||= begin
|
193
|
+
@config[:backend_options] ||= {}
|
194
|
+
require "message_bus/backends/#{backend}"
|
195
|
+
MessageBus::BACKENDS[backend].new @config
|
196
|
+
end
|
186
197
|
end
|
187
198
|
end
|
188
199
|
|
200
|
+
def backend
|
201
|
+
@config[:backend] || :redis
|
202
|
+
end
|
203
|
+
|
189
204
|
def enable_diagnostics
|
190
205
|
MessageBus::Diagnostics.enable
|
191
206
|
end
|
@@ -333,11 +348,11 @@ module MessageBus::Implementation
|
|
333
348
|
# a keepalive will run every N seconds, if it fails
|
334
349
|
# process is killed
|
335
350
|
def keepalive_interval=(interval)
|
336
|
-
|
351
|
+
configure(keepalive_interval: interval)
|
337
352
|
end
|
338
353
|
|
339
354
|
def keepalive_interval
|
340
|
-
@keepalive_interval || 60
|
355
|
+
@config[:keepalive_interval] || 60
|
341
356
|
end
|
342
357
|
|
343
358
|
protected
|
@@ -459,6 +474,8 @@ module MessageBus::Implementation
|
|
459
474
|
|
460
475
|
@mutex.synchronize do
|
461
476
|
raise MessageBus::BusDestroyed if @destroyed
|
477
|
+
next unless @subscriptions
|
478
|
+
|
462
479
|
globals = @subscriptions[nil]
|
463
480
|
locals = @subscriptions[msg.site_id] if msg.site_id
|
464
481
|
|