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