message_bus 4.2.0 → 4.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintrc.js +9 -0
- data/.github/workflows/ci.yml +4 -4
- data/CHANGELOG +16 -0
- data/Dockerfile +2 -2
- data/README.md +1 -1
- data/assets/message-bus.js +37 -22
- data/lib/message_bus/backends/redis.rb +23 -1
- data/lib/message_bus/version.rb +1 -1
- data/lib/message_bus.rb +8 -3
- data/package-lock.json +541 -430
- data/package.json +1 -1
- data/spec/assets/SpecHelper.js +10 -4
- data/spec/assets/message-bus.spec.js +70 -1
- data/spec/lib/message_bus/backend_spec.rb +0 -7
- data/spec/lib/message_bus_spec.rb +52 -20
- data/vendor/assets/javascripts/message-bus.js +37 -22
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15a820bf3ce7658e466132cbc2dd41c4f71b5c68db2e993437698192922377b9
|
4
|
+
data.tar.gz: 2c698b0e82d3d17dc3c0aa682e34ffaf32713f47fe207c1e8b1d55d2fb7cbe48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ea1a5c7a8c80bdddb487eed1442e6364b37518407c1809b0fe76bc3bf5fcba96bb66df04d02d4e491350d415abbae1cd0ecc91ef1079838d6455b6063c0459f
|
7
|
+
data.tar.gz: 981cc3d93b7ca7a3af50179c9450033f4e4566edca5d1269c73d3fd94952f5a77d5ce14b87aa58bc5845e377a2c5c6cbe64cd1dc7905dd7689dfe1295f0668cf
|
data/.eslintrc.js
CHANGED
@@ -11,4 +11,13 @@ module.exports = {
|
|
11
11
|
},
|
12
12
|
rules: {},
|
13
13
|
ignorePatterns: ['/vendor', '/doc', '/assets/jquery-1.8.2.js'],
|
14
|
+
overrides: [
|
15
|
+
{
|
16
|
+
// Enable async/await in tests only
|
17
|
+
files: ["spec/**/*"],
|
18
|
+
parserOptions: {
|
19
|
+
ecmaVersion: 2022,
|
20
|
+
},
|
21
|
+
},
|
22
|
+
],
|
14
23
|
};
|
data/.github/workflows/ci.yml
CHANGED
@@ -43,7 +43,7 @@ jobs:
|
|
43
43
|
--health-retries 5
|
44
44
|
|
45
45
|
steps:
|
46
|
-
- uses: actions/checkout@
|
46
|
+
- uses: actions/checkout@v3
|
47
47
|
|
48
48
|
- uses: ruby/setup-ruby@v1
|
49
49
|
with:
|
@@ -51,9 +51,9 @@ jobs:
|
|
51
51
|
bundler-cache: true
|
52
52
|
|
53
53
|
- name: Set up Node.js
|
54
|
-
uses: actions/setup-node@
|
54
|
+
uses: actions/setup-node@v3
|
55
55
|
with:
|
56
|
-
node-version:
|
56
|
+
node-version: 18
|
57
57
|
cache: npm
|
58
58
|
|
59
59
|
- name: Setup npm
|
@@ -74,7 +74,7 @@ jobs:
|
|
74
74
|
runs-on: ubuntu-latest
|
75
75
|
|
76
76
|
steps:
|
77
|
-
- uses: actions/checkout@
|
77
|
+
- uses: actions/checkout@v3
|
78
78
|
|
79
79
|
- name: Release gem
|
80
80
|
uses: discourse/publish-rubygems-action@v2
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
FUTURE
|
2
|
+
|
3
|
+
06-01-2023
|
4
|
+
|
5
|
+
- Version 4.2.1
|
6
|
+
|
7
|
+
- FIX: Ensure non-long-polling requests are always spaced out
|
8
|
+
|
9
|
+
04-11-2022
|
10
|
+
|
11
|
+
- Version 4.2.0
|
12
|
+
|
13
|
+
- FIX: Add redis gem version 5 support
|
14
|
+
- FEATURE: Allow disabling subscriptions without disabling publication
|
15
|
+
|
1
16
|
22-02-2022
|
2
17
|
|
3
18
|
- Version 4.2.0
|
@@ -376,6 +391,7 @@
|
|
376
391
|
|
377
392
|
- Version 2.0.0.beta.5
|
378
393
|
|
394
|
+
- Feature: Memory backend @jeremyevans
|
379
395
|
- Fix: JavaScript unsubscribe was not updating publicly visible MessageBus.callbacks @sam
|
380
396
|
- Fix: When MessageBus is talking to a readonly redis buffering may cause a infinite loop @tgxworld
|
381
397
|
|
data/Dockerfile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
FROM ruby:2.
|
1
|
+
FROM ruby:2.7
|
2
2
|
|
3
3
|
RUN cd /tmp && \
|
4
4
|
wget --quiet https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 && \
|
@@ -10,7 +10,7 @@ WORKDIR /usr/src/app
|
|
10
10
|
|
11
11
|
RUN mkdir -p ./lib/message_bus
|
12
12
|
COPY lib/message_bus/version.rb ./lib/message_bus
|
13
|
-
COPY Gemfile
|
13
|
+
COPY Gemfile *.gemspec ./
|
14
14
|
RUN bundle install
|
15
15
|
|
16
16
|
COPY . .
|
data/README.md
CHANGED
@@ -155,7 +155,7 @@ end)
|
|
155
155
|
|
156
156
|
#### Disabling message_bus
|
157
157
|
|
158
|
-
In certain cases, it is undesirable for message_bus to start up on application start, for example in a Rails application during the `db:create` rake task when using the Postgres backend (which will error trying to connect to the non-existent database to subscribe). You can invoke `MessageBus.off` before the middleware chain is loaded in order to prevent subscriptions and publications from happening; in a Rails app you might do this in an initializer based on some environment variable or some other conditional means.
|
158
|
+
In certain cases, it is undesirable for message_bus to start up on application start, for example in a Rails application during the `db:create` rake task when using the Postgres backend (which will error trying to connect to the non-existent database to subscribe). You can invoke `MessageBus.off` before the middleware chain is loaded in order to prevent subscriptions and publications from happening; in a Rails app you might do this in an initializer based on some environment variable or some other conditional means. If you want to just disable subscribing to the bus but want to continue to allow publications to be made, you can do `MessageBus.off(disable_publish: false)`.
|
159
159
|
|
160
160
|
### Debugging
|
161
161
|
|
data/assets/message-bus.js
CHANGED
@@ -40,7 +40,7 @@
|
|
40
40
|
var pollTimeout = null;
|
41
41
|
var totalAjaxFailures = 0;
|
42
42
|
var totalAjaxCalls = 0;
|
43
|
-
var
|
43
|
+
var lastAjaxStartedAt;
|
44
44
|
|
45
45
|
var isHidden = (function () {
|
46
46
|
var prefixes = ["", "webkit", "ms", "moz"];
|
@@ -156,11 +156,11 @@
|
|
156
156
|
}
|
157
157
|
|
158
158
|
var gotData = false;
|
159
|
-
var
|
159
|
+
var abortedByClient = false;
|
160
160
|
var rateLimited = false;
|
161
161
|
var rateLimitedSeconds;
|
162
162
|
|
163
|
-
|
163
|
+
lastAjaxStartedAt = new Date();
|
164
164
|
totalAjaxCalls += 1;
|
165
165
|
data.__seq = totalAjaxCalls;
|
166
166
|
|
@@ -281,7 +281,7 @@
|
|
281
281
|
rateLimitedSeconds = tryAfter;
|
282
282
|
rateLimited = true;
|
283
283
|
} else if (textStatus === "abort") {
|
284
|
-
|
284
|
+
abortedByClient = true;
|
285
285
|
} else {
|
286
286
|
failCount += 1;
|
287
287
|
totalAjaxFailures += 1;
|
@@ -290,27 +290,40 @@
|
|
290
290
|
complete: function () {
|
291
291
|
ajaxInProgress = false;
|
292
292
|
|
293
|
-
var
|
293
|
+
var inLongPollingMode = shouldLongPoll();
|
294
|
+
var startNextRequestAfter;
|
294
295
|
try {
|
295
296
|
if (rateLimited) {
|
296
|
-
|
297
|
-
|
298
|
-
|
297
|
+
// Respect `Retry-After` header
|
298
|
+
startNextRequestAfter = Math.max(
|
299
|
+
me.minPollInterval,
|
300
|
+
rateLimitedSeconds * 1000
|
301
|
+
);
|
302
|
+
} else if (abortedByClient) {
|
303
|
+
// Immediately trigger another poll
|
304
|
+
startNextRequestAfter = me.minPollInterval;
|
305
|
+
} else if (failCount > 2) {
|
306
|
+
// Linear backoff up to maxPollInterval
|
307
|
+
startNextRequestAfter = Math.min(
|
308
|
+
me.callbackInterval * failCount,
|
309
|
+
me.maxPollInterval
|
310
|
+
);
|
311
|
+
} else if (inLongPollingMode && gotData) {
|
312
|
+
// Immediately trigger another poll
|
313
|
+
startNextRequestAfter = me.minPollInterval;
|
299
314
|
} else {
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
if (interval > me.maxPollInterval) {
|
307
|
-
interval = me.maxPollInterval;
|
308
|
-
}
|
315
|
+
// Trigger next poll N seconds after the last one **started**
|
316
|
+
var targetRequestInterval = inLongPollingMode
|
317
|
+
? me.callbackInterval
|
318
|
+
: me.backgroundCallbackInterval;
|
319
|
+
|
320
|
+
var elapsedSinceLastAjaxStarted = new Date() - lastAjaxStartedAt;
|
309
321
|
|
310
|
-
|
322
|
+
startNextRequestAfter =
|
323
|
+
targetRequestInterval - elapsedSinceLastAjaxStarted;
|
311
324
|
|
312
|
-
if (
|
313
|
-
|
325
|
+
if (startNextRequestAfter < 100) {
|
326
|
+
startNextRequestAfter = 100;
|
314
327
|
}
|
315
328
|
}
|
316
329
|
} catch (e) {
|
@@ -328,7 +341,7 @@
|
|
328
341
|
pollTimeout = setTimeout(function () {
|
329
342
|
pollTimeout = null;
|
330
343
|
poll();
|
331
|
-
},
|
344
|
+
}, startNextRequestAfter);
|
332
345
|
}
|
333
346
|
|
334
347
|
me.longPoll = null;
|
@@ -367,7 +380,9 @@
|
|
367
380
|
totalAjaxFailures
|
368
381
|
);
|
369
382
|
console.log(
|
370
|
-
"Last ajax call: " +
|
383
|
+
"Last ajax call: " +
|
384
|
+
(new Date() - lastAjaxStartedAt) / 1000 +
|
385
|
+
" seconds ago"
|
371
386
|
);
|
372
387
|
},
|
373
388
|
|
@@ -346,7 +346,29 @@ LUA
|
|
346
346
|
private
|
347
347
|
|
348
348
|
def new_redis_connection
|
349
|
-
|
349
|
+
config = @redis_config.filter do |k, v|
|
350
|
+
# This is not ideal, required for Redis gem version 5
|
351
|
+
# redis-client no longer accepts arbitrary params
|
352
|
+
# anything unknown will error out.
|
353
|
+
# https://github.com/redis-rb/redis-client/blob/4c8e05acfb3477c1651138a4924616e79e6116f2/lib/redis_client/config.rb#L21-L39
|
354
|
+
#
|
355
|
+
#
|
356
|
+
# We should be doing the opposite and allowlisting params
|
357
|
+
# or splitting the object up. Starting with the smallest change that is backwards compatible
|
358
|
+
![
|
359
|
+
:backend,
|
360
|
+
:logger,
|
361
|
+
:long_polling_enabled,
|
362
|
+
:backend_options,
|
363
|
+
:base_route,
|
364
|
+
:client_message_filters,
|
365
|
+
:site_id_lookup,
|
366
|
+
:group_id_lookup,
|
367
|
+
:user_id_lookup,
|
368
|
+
:transport_codec
|
369
|
+
].include?(k)
|
370
|
+
end
|
371
|
+
::Redis.new(config)
|
350
372
|
end
|
351
373
|
|
352
374
|
# redis connection used for publishing messages
|
data/lib/message_bus/version.rb
CHANGED
data/lib/message_bus.rb
CHANGED
@@ -40,6 +40,7 @@ module MessageBus::Implementation
|
|
40
40
|
@config = {}
|
41
41
|
@mutex = Synchronizer.new
|
42
42
|
@off = false
|
43
|
+
@off_disable_publish = false
|
43
44
|
@destroyed = false
|
44
45
|
@timer_thread = nil
|
45
46
|
@subscriber_thread = nil
|
@@ -160,15 +161,17 @@ module MessageBus::Implementation
|
|
160
161
|
end
|
161
162
|
|
162
163
|
# Disables publication to the bus
|
164
|
+
# @param [Boolean] disable_publish Whether or not to disable publishing
|
163
165
|
# @return [void]
|
164
|
-
def off
|
166
|
+
def off(disable_publish: true)
|
165
167
|
@off = true
|
168
|
+
@off_disable_publish = disable_publish
|
166
169
|
end
|
167
170
|
|
168
171
|
# Enables publication to the bus
|
169
172
|
# @return [void]
|
170
173
|
def on
|
171
|
-
@destroyed = @off = false
|
174
|
+
@destroyed = @off = @off_disable_publish = false
|
172
175
|
end
|
173
176
|
|
174
177
|
# Overrides existing configuration
|
@@ -338,7 +341,7 @@ module MessageBus::Implementation
|
|
338
341
|
# @raise [MessageBus::InvalidMessage] if attempting to put permission restrictions on a globally-published message
|
339
342
|
# @raise [MessageBus::InvalidMessageTarget] if attempting to publish to a empty group of users
|
340
343
|
def publish(channel, data, opts = nil)
|
341
|
-
return if @
|
344
|
+
return if @off_disable_publish
|
342
345
|
|
343
346
|
@mutex.synchronize do
|
344
347
|
raise ::MessageBus::BusDestroyed if @destroyed
|
@@ -664,6 +667,8 @@ module MessageBus::Implementation
|
|
664
667
|
end
|
665
668
|
|
666
669
|
def subscribe_impl(channel, site_id, last_id, &blk)
|
670
|
+
return if @off
|
671
|
+
|
667
672
|
raise MessageBus::BusDestroyed if @destroyed
|
668
673
|
|
669
674
|
if last_id >= 0
|