message_bus 3.3.6 → 3.3.7
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.
- checksums.yaml +4 -4
- data/.eslintrc.js +10 -2
- data/.github/workflows/ci.yml +36 -19
- data/CHANGELOG +15 -8
- data/DEV.md +0 -2
- data/Gemfile +0 -27
- data/LICENSE +1 -1
- data/README.md +10 -10
- data/Rakefile +12 -7
- data/assets/message-bus-ajax.js +3 -3
- data/bench/codecs/marshal.rb +1 -1
- data/bench/codecs/packed_string.rb +1 -1
- data/examples/bench/bench.lua +2 -2
- data/lib/message_bus/backends/base.rb +3 -3
- data/lib/message_bus/backends/postgres.rb +7 -3
- data/lib/message_bus/backends/redis.rb +1 -1
- data/lib/message_bus/client.rb +3 -7
- data/lib/message_bus/connection_manager.rb +1 -1
- data/lib/message_bus/distributed_cache.rb +2 -1
- data/lib/message_bus/http_client.rb +2 -2
- data/lib/message_bus/rack/diagnostics.rb +30 -8
- data/lib/message_bus/rack/middleware.rb +6 -0
- data/lib/message_bus/rack/thin_ext.rb +1 -1
- data/lib/message_bus/version.rb +1 -1
- data/lib/message_bus.rb +6 -6
- data/message_bus.gemspec +20 -5
- data/package-lock.json +1575 -23
- data/package.json +7 -2
- data/spec/assets/SpecHelper.js +6 -5
- data/spec/assets/message-bus.spec.js +9 -6
- data/spec/helpers.rb +17 -6
- data/spec/integration/http_client_spec.rb +1 -1
- data/spec/lib/message_bus/backend_spec.rb +12 -44
- data/spec/lib/message_bus/client_spec.rb +6 -6
- data/spec/lib/message_bus/distributed_cache_spec.rb +5 -7
- data/spec/lib/message_bus/multi_process_spec.rb +1 -1
- data/spec/lib/message_bus/rack/middleware_spec.rb +16 -5
- data/spec/lib/message_bus_spec.rb +10 -6
- data/spec/spec_helper.rb +8 -9
- data/spec/support/jasmine-browser.json +16 -0
- metadata +220 -14
- data/spec/assets/support/jasmine.yml +0 -126
- data/spec/assets/support/jasmine_helper.rb +0 -11
- data/vendor/assets/javascripts/message-bus-ajax.js +0 -38
- data/vendor/assets/javascripts/message-bus.js +0 -549
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16601ac02268a477a94bf0347922162f66ce17dfdba1c4c655d576b46e78a79c
|
4
|
+
data.tar.gz: 746e2295f873d9cfe75c28b079b406bb42329a992146d414c63292c2148a8f48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d048dde14c63d5abdda283571cb9c2be1b7fc809a94c7f0b4ec2eaa4785da03bc47535264741f65cfa1d66c75e1b0169ea0de39449456b9c791ba91518d62e9
|
7
|
+
data.tar.gz: 0cfbed1cab954e33805c94c7662c9094276615d5f338168da48d26f033da0f42685024b87aaee64d221e192d0592cd655fba7473da8d973616b218ce2858b045
|
data/.eslintrc.js
CHANGED
@@ -4,10 +4,18 @@ module.exports = {
|
|
4
4
|
browser: true,
|
5
5
|
es2021: false,
|
6
6
|
},
|
7
|
-
extends:
|
7
|
+
extends: 'eslint:recommended',
|
8
8
|
parserOptions: {
|
9
9
|
ecmaVersion: 2015,
|
10
|
-
sourceType:
|
10
|
+
sourceType: 'module',
|
11
11
|
},
|
12
12
|
rules: {},
|
13
|
+
ignorePatterns: [
|
14
|
+
'/vendor',
|
15
|
+
'/doc',
|
16
|
+
'/assets/babel.min.js',
|
17
|
+
'/assets/jquery-1.8.2.js',
|
18
|
+
'/assets/react-dom.js',
|
19
|
+
'/assets/react.js',
|
20
|
+
],
|
13
21
|
};
|
data/.github/workflows/ci.yml
CHANGED
@@ -4,7 +4,7 @@ on:
|
|
4
4
|
pull_request:
|
5
5
|
push:
|
6
6
|
branches:
|
7
|
-
-
|
7
|
+
- main
|
8
8
|
|
9
9
|
env:
|
10
10
|
PGHOST: localhost
|
@@ -15,40 +15,57 @@ env:
|
|
15
15
|
jobs:
|
16
16
|
build:
|
17
17
|
runs-on: ubuntu-latest
|
18
|
-
name: Ruby ${{ matrix.ruby }}
|
18
|
+
name: Ruby ${{ matrix.ruby }} (redis ${{ matrix.redis }})
|
19
|
+
timeout-minutes: 10
|
20
|
+
|
19
21
|
services:
|
20
22
|
postgres:
|
21
|
-
image: postgres:
|
23
|
+
image: postgres:14.0
|
22
24
|
env:
|
23
25
|
POSTGRES_PASSWORD: postgres
|
24
26
|
ports:
|
25
27
|
- 5432:5432
|
26
28
|
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
29
|
+
redis:
|
30
|
+
image: ${{ format('redis:{0}', matrix.redis) }}
|
31
|
+
ports:
|
32
|
+
- 6379:6379
|
33
|
+
options: >-
|
34
|
+
--health-cmd "redis-cli ping"
|
35
|
+
--health-interval 10s
|
36
|
+
--health-timeout 5s
|
37
|
+
--health-retries 5
|
38
|
+
|
27
39
|
strategy:
|
40
|
+
fail-fast: false
|
28
41
|
matrix:
|
29
|
-
ruby: ["
|
42
|
+
ruby: ["3.0", "2.7", "2.6"]
|
43
|
+
redis: ["5", "6"]
|
44
|
+
|
30
45
|
steps:
|
31
46
|
- uses: actions/checkout@v2
|
32
|
-
|
47
|
+
|
48
|
+
- uses: ruby/setup-ruby@v1
|
33
49
|
with:
|
34
50
|
ruby-version: ${{ matrix.ruby }}
|
35
|
-
|
36
|
-
|
51
|
+
bundler-cache: true # 'bundle install' and cache
|
52
|
+
|
53
|
+
- name: Set up Node.js
|
54
|
+
uses: actions/setup-node@v2
|
37
55
|
with:
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
56
|
+
node-version: 16
|
57
|
+
cache: npm
|
58
|
+
|
59
|
+
- name: Setup npm
|
60
|
+
run: npm install
|
61
|
+
|
42
62
|
- name: Create Database
|
43
63
|
run: |
|
44
64
|
createdb message_bus_test
|
45
|
-
|
46
|
-
uses: shogo82148/actions-setup-redis@v1
|
47
|
-
with:
|
48
|
-
redis-version: '5.x'
|
49
|
-
- name: Setup gems
|
50
|
-
run: |
|
51
|
-
bundle config path vendor/bundle
|
52
|
-
bundle install --jobs 4
|
65
|
+
|
53
66
|
- name: Tests
|
54
67
|
run: bundle exec rake
|
68
|
+
timeout-minutes: 3
|
69
|
+
|
70
|
+
- name: Linting
|
71
|
+
run: npx eslint .
|
data/CHANGELOG
CHANGED
@@ -1,10 +1,17 @@
|
|
1
|
+
15-12-2021
|
2
|
+
|
3
|
+
- Version 3.3.7
|
4
|
+
|
5
|
+
- FIX: Prevent simple polling from clobbering the session
|
6
|
+
- SECURITY: Fix path traversal on diagnostics route.
|
7
|
+
|
1
8
|
31-05-2021
|
2
9
|
|
3
10
|
- Version 3.3.6
|
4
11
|
|
5
12
|
- FEATURE: Introduce support for transport codecs
|
6
13
|
- FIX: event subscription leak in JS after start/stop/start sequence
|
7
|
-
- FEATURE: MessageBus.onVisibilityChange() can be used to trigger a
|
14
|
+
- FEATURE: MessageBus.onVisibilityChange() can be used to trigger a visibility change check by hand
|
8
15
|
|
9
16
|
28-04-2021
|
10
17
|
|
@@ -62,7 +69,7 @@
|
|
62
69
|
|
63
70
|
- Version 3.2.0
|
64
71
|
|
65
|
-
- FIX:
|
72
|
+
- FIX: compatibility with Rails 6.0.3, note: apps without ActionDispatch::Flash may stop working after this upgrade
|
66
73
|
to correct this disable middleware injection with `config.skip_message_bus_middleware = true` and configure middleware by hand with `app.middleware.use(MessageBus::Rack::Middleware)`
|
67
74
|
|
68
75
|
28-04-2020
|
@@ -189,7 +196,7 @@
|
|
189
196
|
|
190
197
|
- Version 2.1.6
|
191
198
|
|
192
|
-
- FEATURE: `
|
199
|
+
- FEATURE: `MessageBus.publish` accepts option `site_id` to publish to a site
|
193
200
|
- FEATURE: Added MessageBus::DistributedCache for cross process caching
|
194
201
|
- PERF: Use monotonic times in timer thread
|
195
202
|
- FEATURE: min poll interval is now configurable client side
|
@@ -253,7 +260,7 @@
|
|
253
260
|
|
254
261
|
- Version 2.0.6
|
255
262
|
|
256
|
-
- Fix: correct after_fork so it correctly
|
263
|
+
- Fix: correct after_fork so it correctly disconnects redis
|
257
264
|
- Fix: correct message_bus #destroy used in tests to clean up spec (deadlock)
|
258
265
|
- Fix: deliver backlog unconditionally when polling (and not long polling)
|
259
266
|
|
@@ -323,7 +330,7 @@
|
|
323
330
|
|
324
331
|
- Version 2.0.0.beta.6
|
325
332
|
|
326
|
-
- Feature: Support standalone
|
333
|
+
- Feature: Support standalone operation without depending on jQuery @nathanstitt
|
327
334
|
- Feature: Support a noconflict mode @nathanstitt
|
328
335
|
- Feature: Support JSON POST payload @nathanstitt
|
329
336
|
|
@@ -369,7 +376,7 @@
|
|
369
376
|
- Version 1.1.0
|
370
377
|
- Fix: keep track of client sequence on server, abandon old subscribes
|
371
378
|
- Fix: rare concurrency issue when subscribing concurrently
|
372
|
-
-
|
379
|
+
- Feature: remove most jQuery dependency from message-bus.js
|
373
380
|
|
374
381
|
09-07-2015
|
375
382
|
- Version 1.0.16
|
@@ -393,7 +400,7 @@
|
|
393
400
|
|
394
401
|
28-05-2015
|
395
402
|
- Version 1.0.12
|
396
|
-
- Feature: Support client_id
|
403
|
+
- Feature: Support client_id targeted message
|
397
404
|
|
398
405
|
06-05-2015
|
399
406
|
- Version 1.0.11
|
@@ -402,7 +409,7 @@
|
|
402
409
|
01-05-2015
|
403
410
|
- Version: 1.0.10
|
404
411
|
- Feature: no longer depends on EventMachine (only used for Thin backend)
|
405
|
-
- Feature:
|
412
|
+
- Feature: reliable pub sub will queue messages in memory if redis is readonly, configurable
|
406
413
|
- Fix: if redis is flushed we will continue to deliver messages
|
407
414
|
|
408
415
|
23-03-2015
|
data/DEV.md
CHANGED
data/Gemfile
CHANGED
@@ -3,30 +3,3 @@ source 'https://rubygems.org'
|
|
3
3
|
|
4
4
|
# Specify your gem's dependencies in message_bus.gemspec
|
5
5
|
gemspec
|
6
|
-
|
7
|
-
group :test do
|
8
|
-
gem 'minitest'
|
9
|
-
gem 'minitest-hooks'
|
10
|
-
gem 'minitest-global_expectations'
|
11
|
-
gem 'rake'
|
12
|
-
gem 'http_parser.rb'
|
13
|
-
gem 'thin'
|
14
|
-
gem 'rack-test', require: 'rack/test'
|
15
|
-
gem 'jasmine'
|
16
|
-
gem 'puma'
|
17
|
-
gem 'm'
|
18
|
-
end
|
19
|
-
|
20
|
-
group :test, :development do
|
21
|
-
gem 'byebug'
|
22
|
-
gem 'oj'
|
23
|
-
end
|
24
|
-
|
25
|
-
group :development do
|
26
|
-
gem 'yard'
|
27
|
-
gem 'rubocop-discourse', require: false
|
28
|
-
gem 'rubocop-rspec', require: false
|
29
|
-
end
|
30
|
-
|
31
|
-
gem 'rack'
|
32
|
-
gem 'concurrent-ruby' # for distributed-cache
|
data/LICENSE
CHANGED
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Read the generated docs: <https://www.rubydoc.info/gems/message_bus>
|
|
12
12
|
|
13
13
|
## Ruby version support
|
14
14
|
|
15
|
-
MessageBus only support officially supported versions of Ruby; as of [
|
15
|
+
MessageBus only support officially supported versions of Ruby; as of [2021-03-31](https://www.ruby-lang.org/en/downloads/branches/) this means we only support Ruby version 2.6 and up.
|
16
16
|
|
17
17
|
## Can you handle concurrent requests?
|
18
18
|
|
@@ -68,19 +68,19 @@ id = MessageBus.last_id("/channel")
|
|
68
68
|
MessageBus.backlog "/channel", id
|
69
69
|
```
|
70
70
|
|
71
|
-
###
|
71
|
+
### Targeted messages
|
72
72
|
|
73
|
-
Messages can be
|
73
|
+
Messages can be targeted to particular clients by supplying the `client_ids` option when publishing a message.
|
74
74
|
|
75
75
|
```ruby
|
76
76
|
MessageBus.publish "/channel", "hello", client_ids: ["XXX", "YYY"] # (using MessageBus.clientId)
|
77
77
|
```
|
78
78
|
|
79
|
-
By configuring the `user_id_lookup` and `group_ids_lookup` options with a Proc or Lambda which will be called with a [Rack specification environment](https://github.com/rack/rack/blob/master/SPEC.rdoc#the-environment-), messages can be
|
79
|
+
By configuring the `user_id_lookup` and `group_ids_lookup` options with a Proc or Lambda which will be called with a [Rack specification environment](https://github.com/rack/rack/blob/master/SPEC.rdoc#the-environment-), messages can be targeted to particular clients users or groups by supplying either the `user_ids` or `group_ids` options when publishing a message.
|
80
80
|
|
81
81
|
```ruby
|
82
82
|
MessageBus.configure(user_id_lookup: proc do |env|
|
83
|
-
# this lookup occurs on JS-client
|
83
|
+
# this lookup occurs on JS-client polling, so that server can retrieve backlog
|
84
84
|
# for the client considering/matching/filtering user_ids set on published messages
|
85
85
|
# if user_id is not set on publish time, any user_id returned here will receive the message
|
86
86
|
# return the user id here
|
@@ -98,7 +98,7 @@ end)
|
|
98
98
|
MessageBus.publish "/channel", "hello", group_ids: [1, 2, 3]
|
99
99
|
|
100
100
|
# example of MessageBus to set user_ids from an initializer in Rails and Devise:
|
101
|
-
# config/
|
101
|
+
# config/initializers/message_bus.rb
|
102
102
|
MessageBus.user_id_lookup do |env|
|
103
103
|
req = Rack::Request.new(env)
|
104
104
|
|
@@ -109,13 +109,13 @@ MessageBus.user_id_lookup do |env|
|
|
109
109
|
end
|
110
110
|
```
|
111
111
|
|
112
|
-
If both `user_ids` and `group_ids` options are supplied when publishing a message, the message will be
|
112
|
+
If both `user_ids` and `group_ids` options are supplied when publishing a message, the message will be targeted at clients with lookup return values that matches on either the `user_ids` **or** the `group_ids` options.
|
113
113
|
|
114
114
|
```ruby
|
115
115
|
MessageBus.publish "/channel", "hello", user_ids: [1, 2, 3], group_ids: [1, 2, 3]
|
116
116
|
```
|
117
117
|
|
118
|
-
If the `client_ids` option is supplied with either the `user_ids` or `group_ids` options when
|
118
|
+
If the `client_ids` option is supplied with either the `user_ids` or `group_ids` options when publishing a message, the `client_ids` option will be applied unconditionally and messages will be filtered further using `user_id` or `group_id` clauses.
|
119
119
|
|
120
120
|
```ruby
|
121
121
|
MessageBus.publish "/channel", "hello", client_ids: ["XXX", "YYY"], user_ids: [1, 2, 3], group_ids: [1, 2, 3]
|
@@ -245,7 +245,7 @@ end)
|
|
245
245
|
MessageBus.publish "/channel", "some message"
|
246
246
|
|
247
247
|
# you can also choose to pass the `:site_id`.
|
248
|
-
# This takes
|
248
|
+
# This takes precedence over whatever `site_id_lookup`
|
249
249
|
# returns
|
250
250
|
MessageBus.publish "/channel", "some message", site_id: "site-id"
|
251
251
|
|
@@ -454,7 +454,7 @@ using a packed string encoder.
|
|
454
454
|
|
455
455
|
Keep in mind, much of MessageBus internals and supporting tools expect data to be converted to JSON and back, if you use a naive (and fast) `Marshal` based codec you may need to limit the features you use. Specifically the Postgresql backend expects the codec never to return a string with `\u0000`, additionally some classes like DistributedCache expect keys to be converted to Strings.
|
456
456
|
|
457
|
-
Another example may be very large and complicated messages where Oj in
|
457
|
+
Another example may be very large and complicated messages where Oj in compatibility mode outperforms JSON. To opt for the Oj codec use:
|
458
458
|
|
459
459
|
```
|
460
460
|
MessageBus.configure(transport_codec: MessageBus::Codec::Oj.new)
|
data/Rakefile
CHANGED
@@ -4,12 +4,8 @@ require 'rake/testtask'
|
|
4
4
|
require 'bundler'
|
5
5
|
require 'bundler/gem_tasks'
|
6
6
|
require 'bundler/setup'
|
7
|
-
require 'jasmine'
|
8
|
-
|
9
|
-
ENV['JASMINE_CONFIG_PATH'] ||= File.join(Dir.pwd, 'spec', 'assets', 'support', 'jasmine.yml')
|
10
|
-
load 'jasmine/tasks/jasmine.rake'
|
11
|
-
|
12
7
|
require 'rubocop/rake_task'
|
8
|
+
|
13
9
|
RuboCop::RakeTask.new
|
14
10
|
|
15
11
|
require 'yard'
|
@@ -35,7 +31,14 @@ module Bundler
|
|
35
31
|
end
|
36
32
|
end
|
37
33
|
|
38
|
-
|
34
|
+
namespace :jasmine do
|
35
|
+
desc "Run Jasmine tests in headless mode"
|
36
|
+
task 'ci' do
|
37
|
+
if !system("npx jasmine-browser-runner runSpecs")
|
38
|
+
exit 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
39
42
|
|
40
43
|
backends = Dir["lib/message_bus/backends/*.rb"].map { |file| file.match(%r{backends/(?<backend>.*).rb})[:backend] } - ["base"]
|
41
44
|
|
@@ -57,6 +60,8 @@ namespace :spec do
|
|
57
60
|
|
58
61
|
desc "Run integration tests"
|
59
62
|
task :integration do
|
63
|
+
require "socket"
|
64
|
+
|
60
65
|
def port_available?(port)
|
61
66
|
server = TCPServer.open("0.0.0.0", port)
|
62
67
|
server.close
|
@@ -78,7 +83,7 @@ namespace :spec do
|
|
78
83
|
end
|
79
84
|
|
80
85
|
desc "Run tests on all backends, plus client JS tests"
|
81
|
-
task spec: backends.map { |backend| "spec:#{backend}" } + [:
|
86
|
+
task spec: backends.map { |backend| "spec:#{backend}" } + ["jasmine:ci", "spec:integration"]
|
82
87
|
|
83
88
|
desc "Run performance benchmarks on all backends"
|
84
89
|
task :performance do
|
data/assets/message-bus-ajax.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
// as a fallback if jQuery is not present
|
3
3
|
//
|
4
4
|
// Only implements methods & options used by MessageBus
|
5
|
-
(function(global
|
5
|
+
(function(global) {
|
6
6
|
'use strict';
|
7
7
|
if (!global.MessageBus){
|
8
8
|
throw new Error("MessageBus must be loaded before the ajax adapter");
|
@@ -16,7 +16,7 @@
|
|
16
16
|
for (var name in options.headers){
|
17
17
|
xhr.setRequestHeader(name, options.headers[name]);
|
18
18
|
}
|
19
|
-
xhr.setRequestHeader('Content-Type', 'application/
|
19
|
+
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
20
20
|
if (options.messageBus.chunked){
|
21
21
|
options.messageBus.onProgressListener(xhr);
|
22
22
|
}
|
@@ -31,7 +31,7 @@
|
|
31
31
|
options.complete();
|
32
32
|
}
|
33
33
|
}
|
34
|
-
xhr.send(
|
34
|
+
xhr.send(new URLSearchParams(options.data).toString());
|
35
35
|
return xhr;
|
36
36
|
};
|
37
37
|
|
data/bench/codecs/marshal.rb
CHANGED
data/examples/bench/bench.lua
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
-- wrk returns lots of read errors, this is unavoidable cause
|
2
2
|
--
|
3
|
-
-- 1. There is no internal
|
3
|
+
-- 1. There is no internal implementation of chunked encoding in wrk (which would be ideal)
|
4
4
|
--
|
5
5
|
-- 2. MessageBus gem does not provide http keepalive (by design), and can not provide content length
|
6
|
-
-- if MessageBus provided keepalive it would have to be able to
|
6
|
+
-- if MessageBus provided keepalive it would have to be able to re-dispatch requests to rack, something
|
7
7
|
-- that is not supported by the underlying rack hijack protocol, once a req is hijacked it can not be
|
8
8
|
-- returned
|
9
9
|
--
|
@@ -62,7 +62,7 @@ module MessageBus
|
|
62
62
|
attr_accessor :max_backlog_size
|
63
63
|
# @return [Integer] the largest permitted size (number of messages) for the global backlog; beyond this capacity, old messages will be dropped.
|
64
64
|
attr_accessor :max_global_backlog_size
|
65
|
-
# @return [Integer] the longest amount of time a message may live in a backlog before
|
65
|
+
# @return [Integer] the longest amount of time a message may live in a backlog before being removed, in seconds.
|
66
66
|
attr_accessor :max_backlog_age
|
67
67
|
# Typically, backlogs are trimmed whenever we publish to them. This setting allows some tolerance in order to improve performance.
|
68
68
|
# @return [Integer] the interval of publications between which the backlog will not be cleared.
|
@@ -74,7 +74,7 @@ module MessageBus
|
|
74
74
|
# @param [Integer] max_backlog_size the largest permitted size (number of messages) for per-channel backlogs; beyond this capacity, old messages will be dropped.
|
75
75
|
def initialize(config = {}, max_backlog_size = 1000); end
|
76
76
|
|
77
|
-
# Performs routines specific to the backend that are necessary after a process fork, typically
|
77
|
+
# Performs routines specific to the backend that are necessary after a process fork, typically triggered by a forking webserver. Typically this re-opens sockets to the backend.
|
78
78
|
def after_fork
|
79
79
|
raise ConcreteClassMustImplementError
|
80
80
|
end
|
@@ -96,7 +96,7 @@ module MessageBus
|
|
96
96
|
# @param [JSON] data some data to publish to the channel. Must be an object that can be encoded as JSON
|
97
97
|
# @param [Hash] opts
|
98
98
|
# @option opts [Boolean] :queue_in_memory (true) whether or not to hold the message in an in-memory buffer if publication fails, to be re-tried later
|
99
|
-
# @option opts [Integer] :max_backlog_age (`self.max_backlog_age`) the longest amount of time a message may live in a backlog before
|
99
|
+
# @option opts [Integer] :max_backlog_age (`self.max_backlog_age`) the longest amount of time a message may live in a backlog before being removed, in seconds
|
100
100
|
# @option opts [Integer] :max_backlog_size (`self.max_backlog_size`) the largest permitted size (number of messages) for the channel backlog; beyond this capacity, old messages will be dropped
|
101
101
|
#
|
102
102
|
# @return [Integer] the channel-specific ID the message was given
|
@@ -44,6 +44,7 @@ module MessageBus
|
|
44
44
|
@listening_on = {}
|
45
45
|
@available = []
|
46
46
|
@allocated = {}
|
47
|
+
@subscribe_connection = nil
|
47
48
|
@mutex = Mutex.new
|
48
49
|
@pid = Process.pid
|
49
50
|
end
|
@@ -131,7 +132,7 @@ module MessageBus
|
|
131
132
|
listener = Listener.new
|
132
133
|
yield listener
|
133
134
|
|
134
|
-
conn = raw_pg_connection
|
135
|
+
conn = @subscribe_connection = raw_pg_connection
|
135
136
|
conn.exec "LISTEN #{channel}"
|
136
137
|
listener.do_sub.call
|
137
138
|
while listening_on?(channel, obj)
|
@@ -145,6 +146,9 @@ module MessageBus
|
|
145
146
|
|
146
147
|
conn.exec "UNLISTEN #{channel}"
|
147
148
|
nil
|
149
|
+
ensure
|
150
|
+
@subscribe_connection&.close
|
151
|
+
@subscribe_connection = nil
|
148
152
|
end
|
149
153
|
|
150
154
|
def unsubscribe
|
@@ -251,7 +255,7 @@ module MessageBus
|
|
251
255
|
@clear_every = config[:clear_every] || 1
|
252
256
|
end
|
253
257
|
|
254
|
-
# Reconnects to Postgres; used after a process fork, typically
|
258
|
+
# Reconnects to Postgres; used after a process fork, typically triggered by a forking webserver
|
255
259
|
# @see Base#after_fork
|
256
260
|
def after_fork
|
257
261
|
client.reconnect
|
@@ -277,7 +281,7 @@ module MessageBus
|
|
277
281
|
msg = MessageBus::Message.new backlog_id, backlog_id, channel, data
|
278
282
|
payload = msg.encode
|
279
283
|
c.publish postgresql_channel_name, payload
|
280
|
-
if backlog_id % clear_every == 0
|
284
|
+
if backlog_id && backlog_id % clear_every == 0
|
281
285
|
max_backlog_size = (opts && opts[:max_backlog_size]) || self.max_backlog_size
|
282
286
|
max_backlog_age = (opts && opts[:max_backlog_age]) || self.max_backlog_age
|
283
287
|
c.clear_global_backlog(backlog_id, @max_global_backlog_size)
|
@@ -62,7 +62,7 @@ module MessageBus
|
|
62
62
|
@max_backlog_age = 604800
|
63
63
|
end
|
64
64
|
|
65
|
-
# Reconnects to Redis; used after a process fork, typically
|
65
|
+
# Reconnects to Redis; used after a process fork, typically triggered by a forking webserver
|
66
66
|
# @see Base#after_fork
|
67
67
|
def after_fork
|
68
68
|
pub_redis.disconnect!
|
data/lib/message_bus/client.rb
CHANGED
@@ -220,7 +220,7 @@ class MessageBus::Client
|
|
220
220
|
|
221
221
|
private
|
222
222
|
|
223
|
-
# heavily optimised to avoid all
|
223
|
+
# heavily optimised to avoid all unneeded allocations
|
224
224
|
NEWLINE = "\r\n".freeze
|
225
225
|
COLON_SPACE = ": ".freeze
|
226
226
|
HTTP_11 = "HTTP/1.1 200 OK\r\n".freeze
|
@@ -261,7 +261,7 @@ class MessageBus::Client
|
|
261
261
|
@wrote_headers = true
|
262
262
|
end
|
263
263
|
|
264
|
-
# chunked encoding may be "re-chunked" by proxies, so add a
|
264
|
+
# chunked encoding may be "re-chunked" by proxies, so add a separator
|
265
265
|
postfix = NEWLINE + "|" + NEWLINE
|
266
266
|
data = data.gsub(postfix, NEWLINE + "||" + NEWLINE)
|
267
267
|
chunk_length = data.bytesize + postfix.bytesize
|
@@ -275,11 +275,7 @@ class MessageBus::Client
|
|
275
275
|
@async_response << postfix
|
276
276
|
@async_response << NEWLINE
|
277
277
|
else
|
278
|
-
@io.write(chunk_length.to_s(16))
|
279
|
-
@io.write(NEWLINE)
|
280
|
-
@io.write(data)
|
281
|
-
@io.write(postfix)
|
282
|
-
@io.write(NEWLINE)
|
278
|
+
@io.write(chunk_length.to_s(16) << NEWLINE << data << postfix << NEWLINE)
|
283
279
|
end
|
284
280
|
end
|
285
281
|
|
@@ -45,7 +45,8 @@ module MessageBus
|
|
45
45
|
hash = current.hash(message.site_id || DEFAULT_SITE_ID)
|
46
46
|
|
47
47
|
case payload["op"]
|
48
|
-
|
48
|
+
# TODO: consider custom marshal support with a restricted set
|
49
|
+
when "set" then hash[payload["key"]] = payload["marshalled"] ? Marshal.load(Base64.decode64(payload["value"])) : payload["value"] # rubocop:disable Security/MarshalLoad
|
49
50
|
when "delete" then hash.delete(payload["key"])
|
50
51
|
when "clear" then hash.clear
|
51
52
|
end
|
@@ -146,8 +146,8 @@ module MessageBus
|
|
146
146
|
#
|
147
147
|
# A last_message_id may be provided.
|
148
148
|
# * -1 will subscribe to all new messages
|
149
|
-
# * -2 will
|
150
|
-
# * -3 will
|
149
|
+
# * -2 will receive last message + all new messages
|
150
|
+
# * -3 will receive last 2 message + all new messages
|
151
151
|
#
|
152
152
|
# @example Subscribing to a channel with `last_message_id`
|
153
153
|
# client.subscribe("/test", last_message_id: -2) do |payload|
|
@@ -13,6 +13,15 @@ class MessageBus::Rack::Diagnostics
|
|
13
13
|
@bus = config[:message_bus] || MessageBus
|
14
14
|
end
|
15
15
|
|
16
|
+
JS_ASSETS = %w{
|
17
|
+
jquery-1.8.2.js
|
18
|
+
react.js
|
19
|
+
react-dom.js
|
20
|
+
babel.min.js
|
21
|
+
message-bus.js
|
22
|
+
application.jsx
|
23
|
+
}
|
24
|
+
|
16
25
|
# Process an HTTP request from a subscriber client
|
17
26
|
# @param [Rack::Request::Env] env the request environment
|
18
27
|
def call(env)
|
@@ -39,9 +48,9 @@ class MessageBus::Rack::Diagnostics
|
|
39
48
|
end
|
40
49
|
|
41
50
|
asset = route.split('/assets/')[1]
|
42
|
-
|
51
|
+
|
52
|
+
if asset && JS_ASSETS.include?(asset)
|
43
53
|
content = asset_contents(asset)
|
44
|
-
split = asset.split('.')
|
45
54
|
return [200, { 'Content-Type' => 'application/javascript;charset=UTF-8' }, [content]]
|
46
55
|
end
|
47
56
|
|
@@ -75,6 +84,23 @@ class MessageBus::Rack::Diagnostics
|
|
75
84
|
File.expand_path("../../../../assets/#{asset}", __FILE__)
|
76
85
|
end
|
77
86
|
|
87
|
+
def script_tags
|
88
|
+
tags = []
|
89
|
+
|
90
|
+
JS_ASSETS.each do |asset|
|
91
|
+
type =
|
92
|
+
if asset.end_with?('.js')
|
93
|
+
'text/javascript'
|
94
|
+
elsif asset.end_with?('.jsx')
|
95
|
+
'text/jsx'
|
96
|
+
end
|
97
|
+
|
98
|
+
tags << js_asset(asset, type)
|
99
|
+
end
|
100
|
+
|
101
|
+
tags.join("\n")
|
102
|
+
end
|
103
|
+
|
78
104
|
def index
|
79
105
|
html = <<~HTML
|
80
106
|
<!DOCTYPE html>
|
@@ -83,12 +109,8 @@ class MessageBus::Rack::Diagnostics
|
|
83
109
|
</head>
|
84
110
|
<body>
|
85
111
|
<div id="app"></div>
|
86
|
-
|
87
|
-
#{
|
88
|
-
#{js_asset "react-dom.js"}
|
89
|
-
#{js_asset "babel.min.js"}
|
90
|
-
#{js_asset "message-bus.js"}
|
91
|
-
#{js_asset "application.jsx", "text/jsx"}
|
112
|
+
|
113
|
+
#{script_tags}
|
92
114
|
</body>
|
93
115
|
</html>
|
94
116
|
HTML
|
@@ -66,6 +66,12 @@ class MessageBus::Rack::Middleware
|
|
66
66
|
private
|
67
67
|
|
68
68
|
def handle_request(env)
|
69
|
+
# Prevent simple polling from clobbering the session
|
70
|
+
# See: https://github.com/discourse/message_bus/issues/257
|
71
|
+
if (rack_session_options = env[Rack::RACK_SESSION_OPTIONS])
|
72
|
+
rack_session_options[:skip] = true
|
73
|
+
end
|
74
|
+
|
69
75
|
# special debug/test route
|
70
76
|
if @bus.allow_broadcast? && env['PATH_INFO'] == @broadcast_route
|
71
77
|
parsed = Rack::Request.new(env)
|