message_bus 2.1.6 → 2.2.0.pre
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/.rubocop.yml +13 -92
- data/.rubocop_todo.yml +659 -0
- data/.travis.yml +1 -1
- data/CHANGELOG +61 -0
- data/Dockerfile +18 -0
- data/Gemfile +3 -1
- data/Guardfile +0 -1
- data/README.md +188 -101
- data/Rakefile +12 -1
- data/assets/message-bus.js +1 -1
- data/docker-compose.yml +46 -0
- data/examples/bench/config.ru +8 -9
- data/examples/bench/unicorn.conf.rb +1 -1
- data/examples/chat/chat.rb +150 -153
- data/examples/minimal/config.ru +2 -3
- data/lib/message_bus.rb +224 -36
- data/lib/message_bus/backends.rb +7 -0
- data/lib/message_bus/backends/base.rb +184 -0
- data/lib/message_bus/backends/memory.rb +304 -226
- data/lib/message_bus/backends/postgres.rb +359 -318
- data/lib/message_bus/backends/redis.rb +380 -337
- data/lib/message_bus/client.rb +99 -41
- data/lib/message_bus/connection_manager.rb +29 -21
- data/lib/message_bus/diagnostics.rb +50 -41
- data/lib/message_bus/distributed_cache.rb +5 -7
- data/lib/message_bus/message.rb +2 -2
- data/lib/message_bus/rack/diagnostics.rb +65 -55
- data/lib/message_bus/rack/middleware.rb +64 -44
- data/lib/message_bus/rack/thin_ext.rb +13 -9
- data/lib/message_bus/rails/railtie.rb +2 -0
- data/lib/message_bus/timer_thread.rb +2 -2
- data/lib/message_bus/version.rb +2 -1
- data/message_bus.gemspec +3 -2
- data/spec/assets/support/jasmine_helper.rb +1 -1
- data/spec/lib/fake_async_middleware.rb +1 -6
- data/spec/lib/message_bus/assets/asset_encoding_spec.rb +3 -3
- data/spec/lib/message_bus/backend_spec.rb +409 -0
- data/spec/lib/message_bus/client_spec.rb +8 -11
- data/spec/lib/message_bus/connection_manager_spec.rb +8 -14
- data/spec/lib/message_bus/distributed_cache_spec.rb +0 -4
- data/spec/lib/message_bus/multi_process_spec.rb +6 -7
- data/spec/lib/message_bus/rack/middleware_spec.rb +47 -43
- data/spec/lib/message_bus/timer_thread_spec.rb +0 -2
- data/spec/lib/message_bus_spec.rb +59 -43
- data/spec/spec_helper.rb +16 -4
- metadata +12 -9
- data/spec/lib/message_bus/backends/postgres_spec.rb +0 -221
- data/spec/lib/message_bus/backends/redis_spec.rb +0 -271
data/examples/minimal/config.ru
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'message_bus'
|
2
2
|
|
3
|
-
#MessageBus.long_polling_interval = 1000 * 2
|
3
|
+
# MessageBus.long_polling_interval = 1000 * 2
|
4
4
|
|
5
5
|
use MessageBus::Rack::Middleware
|
6
|
-
run lambda { |
|
7
|
-
|
6
|
+
run lambda { |_env| [200, { "Content-Type" => "text/html" }, ["Howdy"]] }
|
data/lib/message_bus.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "monitor"
|
3
4
|
require "set"
|
4
5
|
require "message_bus/version"
|
@@ -15,13 +16,16 @@ if defined?(::Rails)
|
|
15
16
|
require 'message_bus/rails/railtie'
|
16
17
|
end
|
17
18
|
|
19
|
+
# @see MessageBus::Implementation
|
18
20
|
module MessageBus; end
|
19
21
|
MessageBus::BACKENDS = {}
|
20
22
|
class MessageBus::InvalidMessage < StandardError; end
|
21
23
|
class MessageBus::BusDestroyed < StandardError; end
|
22
24
|
|
25
|
+
# The main server-side interface to a message bus for the purposes of
|
26
|
+
# configuration, publishing and subscribing
|
23
27
|
module MessageBus::Implementation
|
24
|
-
# Configuration options hash
|
28
|
+
# @return [Hash<Symbol => Object>] Configuration options hash
|
25
29
|
attr_reader :config
|
26
30
|
|
27
31
|
# Like Mutex but safe for recursive calls
|
@@ -34,10 +38,13 @@ module MessageBus::Implementation
|
|
34
38
|
@mutex = Synchronizer.new
|
35
39
|
end
|
36
40
|
|
41
|
+
# @param [Boolean] val whether or not to cache static assets for the diagnostics pages
|
42
|
+
# @return [void]
|
37
43
|
def cache_assets=(val)
|
38
44
|
configure(cache_assets: val)
|
39
45
|
end
|
40
46
|
|
47
|
+
# @return [Boolean] whether or not to cache static assets for the diagnostics pages
|
41
48
|
def cache_assets
|
42
49
|
if defined? @config[:cache_assets]
|
43
50
|
@config[:cache_assets]
|
@@ -46,12 +53,17 @@ module MessageBus::Implementation
|
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
56
|
+
# @param [Logger] logger a logger object to be used by the bus
|
57
|
+
# @return [void]
|
49
58
|
def logger=(logger)
|
50
59
|
configure(logger: logger)
|
51
60
|
end
|
52
61
|
|
62
|
+
# @return [Logger] the logger used by the bus. If not explicitly set,
|
63
|
+
# is configured to log to STDOUT at INFO level.
|
53
64
|
def logger
|
54
65
|
return @config[:logger] if @config[:logger]
|
66
|
+
|
55
67
|
require 'logger'
|
56
68
|
logger = Logger.new(STDOUT)
|
57
69
|
logger.level = Logger::INFO
|
@@ -59,32 +71,47 @@ module MessageBus::Implementation
|
|
59
71
|
logger
|
60
72
|
end
|
61
73
|
|
74
|
+
# @return [Boolean] whether or not chunked encoding is enabled. If not
|
75
|
+
# explicitly set, defaults to true.
|
62
76
|
def chunked_encoding_enabled?
|
63
77
|
@config[:chunked_encoding_enabled] == false ? false : true
|
64
78
|
end
|
65
79
|
|
80
|
+
# @param [Boolean] val whether or not to enable chunked encoding
|
81
|
+
# @return [void]
|
66
82
|
def chunked_encoding_enabled=(val)
|
67
83
|
configure(chunked_encoding_enabled: val)
|
68
84
|
end
|
69
85
|
|
86
|
+
# @return [Boolean] whether or not long polling is enabled. If not explicitly
|
87
|
+
# set, defaults to true.
|
70
88
|
def long_polling_enabled?
|
71
89
|
@config[:long_polling_enabled] == false ? false : true
|
72
90
|
end
|
73
91
|
|
92
|
+
# @param [Boolean] val whether or not to enable long polling
|
93
|
+
# @return [void]
|
74
94
|
def long_polling_enabled=(val)
|
75
95
|
configure(long_polling_enabled: val)
|
76
96
|
end
|
77
97
|
|
78
|
-
# The number of simultanuous clients we can service
|
79
|
-
#
|
98
|
+
# @param [Integer] val The number of simultanuous clients we can service;
|
99
|
+
# will revert to polling if we are out of slots
|
100
|
+
# @return [void]
|
80
101
|
def max_active_clients=(val)
|
81
102
|
configure(max_active_clients: val)
|
82
103
|
end
|
83
104
|
|
105
|
+
# @return [Integer] The number of simultanuous clients we can service;
|
106
|
+
# will revert to polling if we are out of slots. Defaults to 1000 if not
|
107
|
+
# explicitly set.
|
84
108
|
def max_active_clients
|
85
109
|
@config[:max_active_clients] || 1000
|
86
110
|
end
|
87
111
|
|
112
|
+
# @return [Boolean] whether or not Rack Hijack is enabled. If not explicitly
|
113
|
+
# set, will default to true, unless we're on Passenger without the ability
|
114
|
+
# to set the advertised_concurrency_level to 0.
|
88
115
|
def rack_hijack_enabled?
|
89
116
|
if @config[:rack_hijack_enabled].nil?
|
90
117
|
enable = true
|
@@ -104,62 +131,107 @@ module MessageBus::Implementation
|
|
104
131
|
@config[:rack_hijack_enabled]
|
105
132
|
end
|
106
133
|
|
134
|
+
# @param [Boolean] val whether or not to enable Rack Hijack
|
135
|
+
# @return [void]
|
107
136
|
def rack_hijack_enabled=(val)
|
108
137
|
configure(rack_hijack_enabled: val)
|
109
138
|
end
|
110
139
|
|
140
|
+
# @param [Integer] millisecs the long-polling interval in milliseconds
|
141
|
+
# @return [void]
|
111
142
|
def long_polling_interval=(millisecs)
|
112
143
|
configure(long_polling_interval: millisecs)
|
113
144
|
end
|
114
145
|
|
146
|
+
# @return [Integer] the long-polling interval in milliseconds. If not
|
147
|
+
# explicitly set, defaults to 25,000.
|
115
148
|
def long_polling_interval
|
116
149
|
@config[:long_polling_interval] || 25 * 1000
|
117
150
|
end
|
118
151
|
|
152
|
+
# @return [Boolean] whether the bus is disabled or not
|
153
|
+
def off?
|
154
|
+
@off
|
155
|
+
end
|
156
|
+
|
157
|
+
# Disables publication to the bus
|
158
|
+
# @return [void]
|
119
159
|
def off
|
120
160
|
@off = true
|
121
161
|
end
|
122
162
|
|
163
|
+
# Enables publication to the bus
|
164
|
+
# @return [void]
|
123
165
|
def on
|
124
|
-
@off = false
|
166
|
+
@destroyed = @off = false
|
125
167
|
end
|
126
168
|
|
169
|
+
# Overrides existing configuration
|
170
|
+
# @param [Hash<Symbol => Object>] config values to merge into existing config
|
171
|
+
# @return [void]
|
127
172
|
def configure(config)
|
128
173
|
@config.merge!(config)
|
129
174
|
end
|
130
175
|
|
131
|
-
#
|
176
|
+
# Overrides existing configuration, explicitly enabling the redis backend
|
177
|
+
# @param [Hash<Symbol => Object>] config values to merge into existing config
|
178
|
+
# @return [void]
|
132
179
|
def redis_config=(config)
|
133
180
|
configure(config.merge(backend: :redis))
|
134
181
|
end
|
135
182
|
|
136
183
|
alias redis_config config
|
137
184
|
|
185
|
+
# @yield [env] a routine to determine the site ID for a subscriber
|
186
|
+
# @yieldparam [optional, Rack::Request::Env] env the subscriber request environment
|
187
|
+
# @yieldreturn [optional, String] the site ID for the subscriber
|
188
|
+
# @return [void]
|
138
189
|
def site_id_lookup(&blk)
|
139
190
|
configure(site_id_lookup: blk) if blk
|
140
191
|
@config[:site_id_lookup]
|
141
192
|
end
|
142
193
|
|
194
|
+
# @yield [env] a routine to determine the user ID for a subscriber (authenticate)
|
195
|
+
# @yieldparam [optional, Rack::Request::Env] env the subscriber request environment
|
196
|
+
# @yieldreturn [optional, String, Integer] the user ID for the subscriber
|
197
|
+
# @return [void]
|
143
198
|
def user_id_lookup(&blk)
|
144
199
|
configure(user_id_lookup: blk) if blk
|
145
200
|
@config[:user_id_lookup]
|
146
201
|
end
|
147
202
|
|
203
|
+
# @yield [env] a routine to determine the group IDs for a subscriber
|
204
|
+
# @yieldparam [optional, Rack::Request::Env] env the subscriber request environment
|
205
|
+
# @yieldreturn [optional, Array<String,Integer>] the group IDs for the subscriber
|
206
|
+
# @return [void]
|
148
207
|
def group_ids_lookup(&blk)
|
149
208
|
configure(group_ids_lookup: blk) if blk
|
150
209
|
@config[:group_ids_lookup]
|
151
210
|
end
|
152
211
|
|
212
|
+
# @yield [env] a routine to determine if a request comes from an admin user
|
213
|
+
# @yieldparam [Rack::Request::Env] env the subscriber request environment
|
214
|
+
# @yieldreturn [Boolean] whether or not the request is from an admin user
|
215
|
+
# @return [void]
|
153
216
|
def is_admin_lookup(&blk)
|
154
217
|
configure(is_admin_lookup: blk) if blk
|
155
218
|
@config[:is_admin_lookup]
|
156
219
|
end
|
157
220
|
|
221
|
+
# @yield [env, e] a routine to handle exceptions raised when handling a subscriber request
|
222
|
+
# @yieldparam [Rack::Request::Env] env the subscriber request environment
|
223
|
+
# @yieldparam [Exception] e the exception that was raised
|
224
|
+
# @yieldreturn [optional, Array<(Integer,Hash,Array)>] a Rack response to be delivered
|
225
|
+
# @return [void]
|
158
226
|
def on_middleware_error(&blk)
|
159
227
|
configure(on_middleware_error: blk) if blk
|
160
228
|
@config[:on_middleware_error]
|
161
229
|
end
|
162
230
|
|
231
|
+
# @yield [env] a routine to determine extra headers to be set on a subscriber response
|
232
|
+
# @yieldparam [Rack::Request::Env] env the subscriber request environment
|
233
|
+
# @yieldreturn [Hash<String => String>] the extra headers to set on the response
|
234
|
+
# @return [void]
|
163
235
|
def extra_response_headers_lookup(&blk)
|
164
236
|
configure(extra_response_headers_lookup: blk) if blk
|
165
237
|
@config[:extra_response_headers_lookup]
|
@@ -175,10 +247,14 @@ module MessageBus::Implementation
|
|
175
247
|
@config[:on_disconnect]
|
176
248
|
end
|
177
249
|
|
250
|
+
# @param [Boolean] val whether or not to allow broadcasting (debugging)
|
251
|
+
# @return [void]
|
178
252
|
def allow_broadcast=(val)
|
179
253
|
configure(allow_broadcast: val)
|
180
254
|
end
|
181
255
|
|
256
|
+
# @return [Boolean] whether or not broadcasting is allowed. If not explicitly
|
257
|
+
# set, defaults to false unless we're in Rails test or development mode.
|
182
258
|
def allow_broadcast?
|
183
259
|
@config[:allow_broadcast] ||=
|
184
260
|
if defined? ::Rails
|
@@ -188,10 +264,14 @@ module MessageBus::Implementation
|
|
188
264
|
end
|
189
265
|
end
|
190
266
|
|
267
|
+
# @param [MessageBus::Backend::Base] pub_sub a configured backend
|
268
|
+
# @return [void]
|
191
269
|
def reliable_pub_sub=(pub_sub)
|
192
270
|
configure(reliable_pub_sub: pub_sub)
|
193
271
|
end
|
194
272
|
|
273
|
+
# @return [MessageBus::Backend::Base] the configured backend. If not
|
274
|
+
# explicitly set, will be loaded based on the configuration provided.
|
195
275
|
def reliable_pub_sub
|
196
276
|
@mutex.synchronize do
|
197
277
|
return nil if @destroyed
|
@@ -208,16 +288,37 @@ module MessageBus::Implementation
|
|
208
288
|
end
|
209
289
|
end
|
210
290
|
|
291
|
+
# @return [Symbol] the name of the backend implementation configured
|
211
292
|
def backend
|
212
293
|
@config[:backend] || :redis
|
213
294
|
end
|
214
295
|
|
296
|
+
# Enables diagnostics tracking
|
297
|
+
# @return [void]
|
215
298
|
def enable_diagnostics
|
216
299
|
MessageBus::Diagnostics.enable(self)
|
217
300
|
end
|
218
301
|
|
302
|
+
# Publishes a message to a channel
|
303
|
+
#
|
304
|
+
# @param [String] channel the name of the channel to which the message should be published
|
305
|
+
# @param [JSON] data some data to publish to the channel. Must be an object that can be encoded as JSON
|
306
|
+
# @param [Hash] opts
|
307
|
+
# @option opts [Array<String>] :client_ids (`nil`) the unique client IDs to which the message should be available. If nil, available to all.
|
308
|
+
# @option opts [Array<String,Integer>] :user_ids (`nil`) the user IDs to which the message should be available. If nil, available to all.
|
309
|
+
# @option opts [Array<String,Integer>] :group_ids (`nil`) the group IDs to which the message should be available. If nil, available to all.
|
310
|
+
# @option opts [String] :site_id (`nil`) the site ID to scope the message to; used for hosting multiple
|
311
|
+
# applications or instances of an application against a single message_bus
|
312
|
+
# @option opts [nil,Integer] :max_backlog_age the longest amount of time a message may live in a backlog before beging removed, in seconds
|
313
|
+
# @option opts [nil,Integer] :max_backlog_size the largest permitted size (number of messages) for the channel backlog; beyond this capacity, old messages will be dropped
|
314
|
+
#
|
315
|
+
# @return [Integer] the channel-specific ID the message was given
|
316
|
+
#
|
317
|
+
# @raise [MessageBus::BusDestroyed] if the bus is destroyed
|
318
|
+
# @raise [MessageBus::InvalidMessage] if attempting to put permission restrictions on a globally-published message
|
219
319
|
def publish(channel, data, opts = nil)
|
220
320
|
return if @off
|
321
|
+
|
221
322
|
@mutex.synchronize do
|
222
323
|
raise ::MessageBus::BusDestroyed if @destroyed
|
223
324
|
end
|
@@ -256,6 +357,17 @@ module MessageBus::Implementation
|
|
256
357
|
reliable_pub_sub.publish(encoded_channel_name, encoded_data, channel_opts)
|
257
358
|
end
|
258
359
|
|
360
|
+
# Subscribe to messages. Each message will be delivered by yielding to the
|
361
|
+
# passed block as soon as it is available. This will block until subscription
|
362
|
+
# is terminated.
|
363
|
+
#
|
364
|
+
# @param [String,nil] channel the name of the channel to which we should
|
365
|
+
# subscribe. If `nil`, messages on every channel will be provided.
|
366
|
+
#
|
367
|
+
# @yield [message] a message-handler block
|
368
|
+
# @yieldparam [MessageBus::Message] message each message as it is delivered
|
369
|
+
#
|
370
|
+
# @return [void]
|
259
371
|
def blocking_subscribe(channel = nil, &blk)
|
260
372
|
if channel
|
261
373
|
reliable_pub_sub.subscribe(encode_channel_name(channel), &blk)
|
@@ -264,45 +376,78 @@ module MessageBus::Implementation
|
|
264
376
|
end
|
265
377
|
end
|
266
378
|
|
267
|
-
|
268
|
-
|
269
|
-
#
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
def decode_channel_name(channel)
|
280
|
-
channel.split(ENCODE_SITE_TOKEN)
|
281
|
-
end
|
282
|
-
|
379
|
+
# Subscribe to messages on a particular channel. Each message since the
|
380
|
+
# last ID specified will be delivered by yielding to the passed block as
|
381
|
+
# soon as it is available. This will not block, but instead the callbacks
|
382
|
+
# will be executed asynchronously in a dedicated subscriber thread.
|
383
|
+
#
|
384
|
+
# @param [String] channel the name of the channel to which we should subscribe
|
385
|
+
# @param [#to_i] last_id the channel-specific ID of the last message that the caller received on the specified channel
|
386
|
+
#
|
387
|
+
# @yield [message] a message-handler block
|
388
|
+
# @yieldparam [MessageBus::Message] message each message as it is delivered
|
389
|
+
#
|
390
|
+
# @return [Proc] the callback block that will be executed
|
283
391
|
def subscribe(channel = nil, last_id = -1, &blk)
|
284
392
|
subscribe_impl(channel, nil, last_id, &blk)
|
285
393
|
end
|
286
394
|
|
287
|
-
#
|
395
|
+
# Subscribe to messages on a particular channel, filtered by the current site
|
396
|
+
# (@see #site_id_lookup). Each message since the last ID specified will be
|
397
|
+
# delivered by yielding to the passed block as soon as it is available. This
|
398
|
+
# will not block, but instead the callbacks will be executed asynchronously
|
399
|
+
# in a dedicated subscriber thread.
|
400
|
+
#
|
401
|
+
# @param [String] channel the name of the channel to which we should subscribe
|
402
|
+
# @param [#to_i] last_id the channel-specific ID of the last message that the caller received on the specified channel
|
403
|
+
#
|
404
|
+
# @yield [message] a message-handler block
|
405
|
+
# @yieldparam [MessageBus::Message] message each message as it is delivered
|
406
|
+
#
|
407
|
+
# @return [Proc] the callback block that will be executed
|
288
408
|
def local_subscribe(channel = nil, last_id = -1, &blk)
|
289
|
-
site_id = site_id_lookup.call if site_id_lookup && !
|
409
|
+
site_id = site_id_lookup.call if site_id_lookup && !global?(channel)
|
290
410
|
subscribe_impl(channel, site_id, last_id, &blk)
|
291
411
|
end
|
292
412
|
|
413
|
+
# Removes a subscription to a particular channel.
|
414
|
+
#
|
415
|
+
# @param [String] channel the name of the channel from which we should unsubscribe
|
416
|
+
# @param [Proc,nil] blk the callback which should be removed. If `nil`, removes all.
|
417
|
+
#
|
418
|
+
# @return [void]
|
293
419
|
def unsubscribe(channel = nil, &blk)
|
294
420
|
unsubscribe_impl(channel, nil, &blk)
|
295
421
|
end
|
296
422
|
|
423
|
+
# Removes a subscription to a particular channel, filtered by the current site
|
424
|
+
# (@see #site_id_lookup).
|
425
|
+
#
|
426
|
+
# @param [String] channel the name of the channel from which we should unsubscribe
|
427
|
+
# @param [Proc,nil] blk the callback which should be removed. If `nil`, removes all.
|
428
|
+
#
|
429
|
+
# @return [void]
|
297
430
|
def local_unsubscribe(channel = nil, &blk)
|
298
431
|
site_id = site_id_lookup.call if site_id_lookup
|
299
432
|
unsubscribe_impl(channel, site_id, &blk)
|
300
433
|
end
|
301
434
|
|
435
|
+
# Get messages from the global backlog since the last ID specified
|
436
|
+
#
|
437
|
+
# @param [#to_i] last_id the global ID of the last message that the caller received
|
438
|
+
#
|
439
|
+
# @return [Array<MessageBus::Message>] all messages published on any channel since the specified last ID
|
302
440
|
def global_backlog(last_id = nil)
|
303
441
|
backlog(nil, last_id)
|
304
442
|
end
|
305
443
|
|
444
|
+
# Get messages from a channel backlog since the last ID specified, filtered by site
|
445
|
+
#
|
446
|
+
# @param [String] channel the name of the channel in question
|
447
|
+
# @param [#to_i] last_id the channel-specific ID of the last message that the caller received on the specified channel
|
448
|
+
# @param [String] site_id the ID of the site by which to filter
|
449
|
+
#
|
450
|
+
# @return [Array<MessageBus::Message>] all messages published to the specified channel since the specified last ID
|
306
451
|
def backlog(channel = nil, last_id = nil, site_id = nil)
|
307
452
|
old =
|
308
453
|
if channel
|
@@ -317,10 +462,21 @@ module MessageBus::Implementation
|
|
317
462
|
old
|
318
463
|
end
|
319
464
|
|
320
|
-
|
465
|
+
# Get the ID of the last message published on a channel, filtered by site
|
466
|
+
#
|
467
|
+
# @param [String] channel the name of the channel in question
|
468
|
+
# @param [String] site_id the ID of the site by which to filter
|
469
|
+
#
|
470
|
+
# @return [Integer] the channel-specific ID of the last message published to the given channel
|
471
|
+
def last_id(channel, site_id = nil)
|
321
472
|
reliable_pub_sub.last_id(encode_channel_name(channel, site_id))
|
322
473
|
end
|
323
474
|
|
475
|
+
# Get the last message published on a channel
|
476
|
+
#
|
477
|
+
# @param [String] channel the name of the channel in question
|
478
|
+
#
|
479
|
+
# @return [MessageBus::Message] the last message published to the given channel
|
324
480
|
def last_message(channel)
|
325
481
|
if last_id = last_id(channel)
|
326
482
|
messages = backlog(channel, last_id - 1)
|
@@ -330,12 +486,17 @@ module MessageBus::Implementation
|
|
330
486
|
end
|
331
487
|
end
|
332
488
|
|
333
|
-
#
|
489
|
+
# Stops listening for publications and stops executing scheduled tasks.
|
490
|
+
# Mostly used in tests to detroy entire bus.
|
491
|
+
# @return [void]
|
334
492
|
def destroy
|
335
493
|
return if @destroyed
|
494
|
+
|
336
495
|
reliable_pub_sub.global_unsubscribe
|
337
496
|
|
338
497
|
@mutex.synchronize do
|
498
|
+
return if @destroyed
|
499
|
+
|
339
500
|
@subscriptions ||= {}
|
340
501
|
@destroyed = true
|
341
502
|
end
|
@@ -343,6 +504,11 @@ module MessageBus::Implementation
|
|
343
504
|
timer.stop
|
344
505
|
end
|
345
506
|
|
507
|
+
# Performs routines that are necessary after a process fork, typically
|
508
|
+
# triggered by a forking webserver. Performs whatever the backend requires
|
509
|
+
# and ensures the server is listening for publications and running
|
510
|
+
# scheduled tasks.
|
511
|
+
# @return [void]
|
346
512
|
def after_fork
|
347
513
|
reliable_pub_sub.after_fork
|
348
514
|
ensure_subscriber_thread
|
@@ -350,17 +516,22 @@ module MessageBus::Implementation
|
|
350
516
|
timer.queue {}
|
351
517
|
end
|
352
518
|
|
519
|
+
# @return [Boolean] whether or not the server is actively listening for
|
520
|
+
# publications on the bus
|
353
521
|
def listening?
|
354
522
|
@subscriber_thread && @subscriber_thread.alive?
|
355
523
|
end
|
356
524
|
|
357
|
-
#
|
525
|
+
# (see MessageBus::Backend::Base#reset!)
|
358
526
|
def reset!
|
359
|
-
reliable_pub_sub.reset!
|
527
|
+
reliable_pub_sub.reset! if reliable_pub_sub
|
360
528
|
end
|
361
529
|
|
530
|
+
# @return [MessageBus::TimerThread] the timer thread used for triggering
|
531
|
+
# scheduled routines at specific times/intervals.
|
362
532
|
def timer
|
363
533
|
return @timer_thread if @timer_thread
|
534
|
+
|
364
535
|
@timer_thread ||= begin
|
365
536
|
t = MessageBus::TimerThread.new
|
366
537
|
t.on_error do |e|
|
@@ -370,18 +541,37 @@ module MessageBus::Implementation
|
|
370
541
|
end
|
371
542
|
end
|
372
543
|
|
373
|
-
#
|
374
|
-
# a keepalive will run every N
|
375
|
-
# process is killed
|
544
|
+
# @param [Integer] interval the keepalive interval in seconds.
|
545
|
+
# Set to 0 to disable; anything higher and a keepalive will run every N
|
546
|
+
# seconds. If it fails, the process is killed.
|
376
547
|
def keepalive_interval=(interval)
|
377
548
|
configure(keepalive_interval: interval)
|
378
549
|
end
|
379
550
|
|
551
|
+
# @return [Integer] the keepalive interval in seconds. If not explicitly set,
|
552
|
+
# defaults to `60`.
|
380
553
|
def keepalive_interval
|
381
554
|
@config[:keepalive_interval] || 60
|
382
555
|
end
|
383
556
|
|
384
|
-
|
557
|
+
private
|
558
|
+
|
559
|
+
ENCODE_SITE_TOKEN = "$|$"
|
560
|
+
|
561
|
+
# encode channel name to include site
|
562
|
+
def encode_channel_name(channel, site_id = nil)
|
563
|
+
if (site_id || site_id_lookup) && !global?(channel)
|
564
|
+
raise ArgumentError.new channel if channel.include? ENCODE_SITE_TOKEN
|
565
|
+
|
566
|
+
"#{channel}#{ENCODE_SITE_TOKEN}#{site_id || site_id_lookup.call}"
|
567
|
+
else
|
568
|
+
channel
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
def decode_channel_name(channel)
|
573
|
+
channel.split(ENCODE_SITE_TOKEN)
|
574
|
+
end
|
385
575
|
|
386
576
|
def global?(channel)
|
387
577
|
channel && channel.start_with?('/global/'.freeze)
|
@@ -410,7 +600,6 @@ module MessageBus::Implementation
|
|
410
600
|
end
|
411
601
|
|
412
602
|
def subscribe_impl(channel, site_id, last_id, &blk)
|
413
|
-
|
414
603
|
raise MessageBus::BusDestroyed if @destroyed
|
415
604
|
|
416
605
|
if last_id >= 0
|
@@ -450,11 +639,11 @@ module MessageBus::Implementation
|
|
450
639
|
end
|
451
640
|
|
452
641
|
raise MessageBus::BusDestroyed if @destroyed
|
642
|
+
|
453
643
|
blk
|
454
644
|
end
|
455
645
|
|
456
646
|
def unsubscribe_impl(channel, site_id, &blk)
|
457
|
-
|
458
647
|
@mutex.synchronize do
|
459
648
|
if blk
|
460
649
|
@subscriptions[site_id][channel].delete blk
|
@@ -462,12 +651,12 @@ module MessageBus::Implementation
|
|
462
651
|
@subscriptions[site_id][channel] = []
|
463
652
|
end
|
464
653
|
end
|
465
|
-
|
466
654
|
end
|
467
655
|
|
468
656
|
def ensure_subscriber_thread
|
469
657
|
@mutex.synchronize do
|
470
658
|
return if (@subscriber_thread && @subscriber_thread.alive?) || @destroyed
|
659
|
+
|
471
660
|
@subscriber_thread = new_subscriber_thread
|
472
661
|
end
|
473
662
|
end
|
@@ -475,7 +664,6 @@ module MessageBus::Implementation
|
|
475
664
|
MIN_KEEPALIVE = 20
|
476
665
|
|
477
666
|
def new_subscriber_thread
|
478
|
-
|
479
667
|
thread = Thread.new do
|
480
668
|
begin
|
481
669
|
global_subscribe_thread unless @destroyed
|
@@ -569,7 +757,6 @@ module MessageBus::Implementation
|
|
569
757
|
a.each(&block) if a
|
570
758
|
end
|
571
759
|
end
|
572
|
-
|
573
760
|
end
|
574
761
|
|
575
762
|
module MessageBus
|
@@ -578,6 +765,7 @@ module MessageBus
|
|
578
765
|
end
|
579
766
|
|
580
767
|
# allows for multiple buses per app
|
768
|
+
# @see MessageBus::Implementation
|
581
769
|
class MessageBus::Instance
|
582
770
|
include MessageBus::Implementation
|
583
771
|
end
|