message_bus 2.0.0.beta.2 → 2.0.0.beta.3

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: a32c3e5353a1c04d239f2ddba14caf80cc63eafa
4
- data.tar.gz: 271d25c01760c1e04d9bd4aca26524629d42b12f
3
+ metadata.gz: 13a3191447206ef44053ab24b6ae199b7e18d11e
4
+ data.tar.gz: 2b5037efdc6052aec3e6087461b26d5902ea0971
5
5
  SHA512:
6
- metadata.gz: 17214e44a821ca146db76a7e22ae3eeada69024c6eaea5351aac4aaaa78bcaf4bebb68aa5cb460c77bc9c172aef5e5ac7e932a040b935e27210a4584f701f7d2
7
- data.tar.gz: 259dafb9a6538358b03a63bad0cb521d89ea3e680be667fb4fb85ffdeea3ee4aeedba31db9e843d209bda73dbc0765000c75ad68fcfc9b888294cc18b97615de
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.2
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 'rspec'
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 built on Redis.
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 = false // in Ruby
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.redis_config = { url: "redis://:p4ssw0rd@10.0.1.1:6380/15" }
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 an in-memory storage backend to ease testing and for very simple deployments
237
- - Build a PostgreSQL backend using NOTIFY and LISTEN
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
- require 'rspec/core'
11
- require 'rspec/core/rake_task'
12
- RSpec::Core::RakeTask.new(:spec) do |spec|
13
- spec.pattern = FileList['spec/**/*_spec.rb']
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
- @cache_assets = val
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
- @logger = logger
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
- @logger = Logger.new(STDOUT)
53
- @logger.level = Logger::INFO
54
- @logger
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
- @chunked_encoding_enabled = val
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
- @long_polling_enabled = val
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
- @max_active_clients = val
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
- @rack_hijack_enabled = true
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
- @rack_hijack_enabled = false
94
+ enable = false
91
95
  if PhusionPassenger.respond_to? :advertised_concurrency_level
92
96
  PhusionPassenger.advertised_concurrency_level = 0
93
- @rack_hijack_enabled = true
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
- @rack_hijack_enabled = val
107
+ configure(rack_hijack_enabled: val)
103
108
  end
104
109
 
105
110
  def long_polling_interval=(millisecs)
106
- @long_polling_interval = millisecs
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
- @redis_config = config
132
+ configure(config.merge(:backend=>:redis))
124
133
  end
125
134
 
126
- def redis_config
127
- @redis_config ||= {}
128
- end
135
+ alias redis_config config
129
136
 
130
137
  def site_id_lookup(&blk)
131
- @site_id_lookup = blk if blk
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
- @user_id_lookup = blk if blk
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
- @group_ids_lookup = blk if blk
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
- @is_admin_lookup = blk if blk
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
- @extra_response_headers_lookup = blk if blk
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
- @on_connect = blk if blk
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
- @on_disconnect = blk if blk
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
- @allow_broadcast = val
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
- @reliable_pub_sub = pub_sub
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 ||= MessageBus::Redis::ReliablePubSub.new redis_config
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
- @keepalive_interval = interval
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