@rails/actioncable 6.1.4 → 6.1.5
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.
- package/app/assets/javascripts/action_cable.js +59 -2
- package/package.json +1 -1
- package/src/connection.js +1 -0
- package/src/index.js +2 -0
- package/src/subscription_guarantor.js +50 -0
- package/src/subscriptions.js +18 -2
- package/CHANGELOG.md +0 -77
@@ -291,6 +291,7 @@
|
|
291
291
|
return this.monitor.recordPing();
|
292
292
|
|
293
293
|
case message_types.confirmation:
|
294
|
+
this.subscriptions.confirmSubscription(identifier);
|
294
295
|
return this.subscriptions.notify(identifier, "connected");
|
295
296
|
|
296
297
|
case message_types.rejection:
|
@@ -360,10 +361,52 @@
|
|
360
361
|
};
|
361
362
|
return Subscription;
|
362
363
|
}();
|
364
|
+
var SubscriptionGuarantor = function() {
|
365
|
+
function SubscriptionGuarantor(subscriptions) {
|
366
|
+
classCallCheck(this, SubscriptionGuarantor);
|
367
|
+
this.subscriptions = subscriptions;
|
368
|
+
this.pendingSubscriptions = [];
|
369
|
+
}
|
370
|
+
SubscriptionGuarantor.prototype.guarantee = function guarantee(subscription) {
|
371
|
+
if (this.pendingSubscriptions.indexOf(subscription) == -1) {
|
372
|
+
logger.log("SubscriptionGuarantor guaranteeing " + subscription.identifier);
|
373
|
+
this.pendingSubscriptions.push(subscription);
|
374
|
+
} else {
|
375
|
+
logger.log("SubscriptionGuarantor already guaranteeing " + subscription.identifier);
|
376
|
+
}
|
377
|
+
this.startGuaranteeing();
|
378
|
+
};
|
379
|
+
SubscriptionGuarantor.prototype.forget = function forget(subscription) {
|
380
|
+
logger.log("SubscriptionGuarantor forgetting " + subscription.identifier);
|
381
|
+
this.pendingSubscriptions = this.pendingSubscriptions.filter(function(s) {
|
382
|
+
return s !== subscription;
|
383
|
+
});
|
384
|
+
};
|
385
|
+
SubscriptionGuarantor.prototype.startGuaranteeing = function startGuaranteeing() {
|
386
|
+
this.stopGuaranteeing();
|
387
|
+
this.retrySubscribing();
|
388
|
+
};
|
389
|
+
SubscriptionGuarantor.prototype.stopGuaranteeing = function stopGuaranteeing() {
|
390
|
+
clearTimeout(this.retryTimeout);
|
391
|
+
};
|
392
|
+
SubscriptionGuarantor.prototype.retrySubscribing = function retrySubscribing() {
|
393
|
+
var _this = this;
|
394
|
+
this.retryTimeout = setTimeout(function() {
|
395
|
+
if (_this.subscriptions && typeof _this.subscriptions.subscribe === "function") {
|
396
|
+
_this.pendingSubscriptions.map(function(subscription) {
|
397
|
+
logger.log("SubscriptionGuarantor resubscribing " + subscription.identifier);
|
398
|
+
_this.subscriptions.subscribe(subscription);
|
399
|
+
});
|
400
|
+
}
|
401
|
+
}, 500);
|
402
|
+
};
|
403
|
+
return SubscriptionGuarantor;
|
404
|
+
}();
|
363
405
|
var Subscriptions = function() {
|
364
406
|
function Subscriptions(consumer) {
|
365
407
|
classCallCheck(this, Subscriptions);
|
366
408
|
this.consumer = consumer;
|
409
|
+
this.guarantor = new SubscriptionGuarantor(this);
|
367
410
|
this.subscriptions = [];
|
368
411
|
}
|
369
412
|
Subscriptions.prototype.create = function create(channelName, mixin) {
|
@@ -378,7 +421,7 @@
|
|
378
421
|
this.subscriptions.push(subscription);
|
379
422
|
this.consumer.ensureActiveConnection();
|
380
423
|
this.notify(subscription, "initialized");
|
381
|
-
this.
|
424
|
+
this.subscribe(subscription);
|
382
425
|
return subscription;
|
383
426
|
};
|
384
427
|
Subscriptions.prototype.remove = function remove(subscription) {
|
@@ -397,6 +440,7 @@
|
|
397
440
|
});
|
398
441
|
};
|
399
442
|
Subscriptions.prototype.forget = function forget(subscription) {
|
443
|
+
this.guarantor.forget(subscription);
|
400
444
|
this.subscriptions = this.subscriptions.filter(function(s) {
|
401
445
|
return s !== subscription;
|
402
446
|
});
|
@@ -410,7 +454,7 @@
|
|
410
454
|
Subscriptions.prototype.reload = function reload() {
|
411
455
|
var _this2 = this;
|
412
456
|
return this.subscriptions.map(function(subscription) {
|
413
|
-
return _this2.
|
457
|
+
return _this2.subscribe(subscription);
|
414
458
|
});
|
415
459
|
};
|
416
460
|
Subscriptions.prototype.notifyAll = function notifyAll(callbackName) {
|
@@ -436,6 +480,18 @@
|
|
436
480
|
return typeof subscription[callbackName] === "function" ? subscription[callbackName].apply(subscription, args) : undefined;
|
437
481
|
});
|
438
482
|
};
|
483
|
+
Subscriptions.prototype.subscribe = function subscribe(subscription) {
|
484
|
+
if (this.sendCommand(subscription, "subscribe")) {
|
485
|
+
this.guarantor.guarantee(subscription);
|
486
|
+
}
|
487
|
+
};
|
488
|
+
Subscriptions.prototype.confirmSubscription = function confirmSubscription(identifier) {
|
489
|
+
var _this4 = this;
|
490
|
+
logger.log("Subscription confirmed " + identifier);
|
491
|
+
this.findAll(identifier).map(function(subscription) {
|
492
|
+
return _this4.guarantor.forget(subscription);
|
493
|
+
});
|
494
|
+
};
|
439
495
|
Subscriptions.prototype.sendCommand = function sendCommand(subscription, command) {
|
440
496
|
var identifier = subscription.identifier;
|
441
497
|
return this.consumer.send({
|
@@ -506,6 +562,7 @@
|
|
506
562
|
exports.INTERNAL = INTERNAL;
|
507
563
|
exports.Subscription = Subscription;
|
508
564
|
exports.Subscriptions = Subscriptions;
|
565
|
+
exports.SubscriptionGuarantor = SubscriptionGuarantor;
|
509
566
|
exports.adapters = adapters;
|
510
567
|
exports.createWebSocketURL = createWebSocketURL;
|
511
568
|
exports.logger = logger;
|
package/package.json
CHANGED
package/src/connection.js
CHANGED
@@ -132,6 +132,7 @@ Connection.prototype.events = {
|
|
132
132
|
case message_types.ping:
|
133
133
|
return this.monitor.recordPing()
|
134
134
|
case message_types.confirmation:
|
135
|
+
this.subscriptions.confirmSubscription(identifier)
|
135
136
|
return this.subscriptions.notify(identifier, "connected")
|
136
137
|
case message_types.rejection:
|
137
138
|
return this.subscriptions.reject(identifier)
|
package/src/index.js
CHANGED
@@ -4,6 +4,7 @@ import Consumer, { createWebSocketURL } from "./consumer"
|
|
4
4
|
import INTERNAL from "./internal"
|
5
5
|
import Subscription from "./subscription"
|
6
6
|
import Subscriptions from "./subscriptions"
|
7
|
+
import SubscriptionGuarantor from "./subscription_guarantor"
|
7
8
|
import adapters from "./adapters"
|
8
9
|
import logger from "./logger"
|
9
10
|
|
@@ -14,6 +15,7 @@ export {
|
|
14
15
|
INTERNAL,
|
15
16
|
Subscription,
|
16
17
|
Subscriptions,
|
18
|
+
SubscriptionGuarantor,
|
17
19
|
adapters,
|
18
20
|
createWebSocketURL,
|
19
21
|
logger,
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import logger from "./logger"
|
2
|
+
|
3
|
+
// Responsible for ensuring channel subscribe command is confirmed, retrying until confirmation is received.
|
4
|
+
// Internal class, not intended for direct user manipulation.
|
5
|
+
|
6
|
+
class SubscriptionGuarantor {
|
7
|
+
constructor(subscriptions) {
|
8
|
+
this.subscriptions = subscriptions
|
9
|
+
this.pendingSubscriptions = []
|
10
|
+
}
|
11
|
+
|
12
|
+
guarantee(subscription) {
|
13
|
+
if(this.pendingSubscriptions.indexOf(subscription) == -1){
|
14
|
+
logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`)
|
15
|
+
this.pendingSubscriptions.push(subscription)
|
16
|
+
}
|
17
|
+
else {
|
18
|
+
logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`)
|
19
|
+
}
|
20
|
+
this.startGuaranteeing()
|
21
|
+
}
|
22
|
+
|
23
|
+
forget(subscription) {
|
24
|
+
logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`)
|
25
|
+
this.pendingSubscriptions = (this.pendingSubscriptions.filter((s) => s !== subscription))
|
26
|
+
}
|
27
|
+
|
28
|
+
startGuaranteeing() {
|
29
|
+
this.stopGuaranteeing()
|
30
|
+
this.retrySubscribing()
|
31
|
+
}
|
32
|
+
|
33
|
+
stopGuaranteeing() {
|
34
|
+
clearTimeout(this.retryTimeout)
|
35
|
+
}
|
36
|
+
|
37
|
+
retrySubscribing() {
|
38
|
+
this.retryTimeout = setTimeout(() => {
|
39
|
+
if (this.subscriptions && typeof(this.subscriptions.subscribe) === "function") {
|
40
|
+
this.pendingSubscriptions.map((subscription) => {
|
41
|
+
logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`)
|
42
|
+
this.subscriptions.subscribe(subscription)
|
43
|
+
})
|
44
|
+
}
|
45
|
+
}
|
46
|
+
, 500)
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
export default SubscriptionGuarantor
|
package/src/subscriptions.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
import Subscription from "./subscription"
|
2
|
+
import SubscriptionGuarantor from "./subscription_guarantor"
|
3
|
+
import logger from "./logger"
|
2
4
|
|
3
5
|
// Collection class for creating (and internally managing) channel subscriptions.
|
4
6
|
// The only method intended to be triggered by the user is ActionCable.Subscriptions#create,
|
@@ -13,6 +15,7 @@ import Subscription from "./subscription"
|
|
13
15
|
export default class Subscriptions {
|
14
16
|
constructor(consumer) {
|
15
17
|
this.consumer = consumer
|
18
|
+
this.guarantor = new SubscriptionGuarantor(this)
|
16
19
|
this.subscriptions = []
|
17
20
|
}
|
18
21
|
|
@@ -29,7 +32,7 @@ export default class Subscriptions {
|
|
29
32
|
this.subscriptions.push(subscription)
|
30
33
|
this.consumer.ensureActiveConnection()
|
31
34
|
this.notify(subscription, "initialized")
|
32
|
-
this.
|
35
|
+
this.subscribe(subscription)
|
33
36
|
return subscription
|
34
37
|
}
|
35
38
|
|
@@ -50,6 +53,7 @@ export default class Subscriptions {
|
|
50
53
|
}
|
51
54
|
|
52
55
|
forget(subscription) {
|
56
|
+
this.guarantor.forget(subscription)
|
53
57
|
this.subscriptions = (this.subscriptions.filter((s) => s !== subscription))
|
54
58
|
return subscription
|
55
59
|
}
|
@@ -60,7 +64,7 @@ export default class Subscriptions {
|
|
60
64
|
|
61
65
|
reload() {
|
62
66
|
return this.subscriptions.map((subscription) =>
|
63
|
-
this.
|
67
|
+
this.subscribe(subscription))
|
64
68
|
}
|
65
69
|
|
66
70
|
notifyAll(callbackName, ...args) {
|
@@ -80,6 +84,18 @@ export default class Subscriptions {
|
|
80
84
|
(typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined))
|
81
85
|
}
|
82
86
|
|
87
|
+
subscribe(subscription) {
|
88
|
+
if (this.sendCommand(subscription, "subscribe")) {
|
89
|
+
this.guarantor.guarantee(subscription)
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
confirmSubscription(identifier) {
|
94
|
+
logger.log(`Subscription confirmed ${identifier}`)
|
95
|
+
this.findAll(identifier).map((subscription) =>
|
96
|
+
this.guarantor.forget(subscription))
|
97
|
+
}
|
98
|
+
|
83
99
|
sendCommand(subscription, command) {
|
84
100
|
const {identifier} = subscription
|
85
101
|
return this.consumer.send({command, identifier})
|
package/CHANGELOG.md
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
## Rails 6.1.4 (June 24, 2021) ##
|
2
|
-
|
3
|
-
* Fix `ArgumentError` with ruby 3.0 on `RemoteConnection#disconnect`.
|
4
|
-
|
5
|
-
*Vladislav*
|
6
|
-
|
7
|
-
|
8
|
-
## Rails 6.1.3.2 (May 05, 2021) ##
|
9
|
-
|
10
|
-
* No changes.
|
11
|
-
|
12
|
-
|
13
|
-
## Rails 6.1.3.1 (March 26, 2021) ##
|
14
|
-
|
15
|
-
* No changes.
|
16
|
-
|
17
|
-
|
18
|
-
## Rails 6.1.3 (February 17, 2021) ##
|
19
|
-
|
20
|
-
* No changes.
|
21
|
-
|
22
|
-
|
23
|
-
## Rails 6.1.2.1 (February 10, 2021) ##
|
24
|
-
|
25
|
-
* No changes.
|
26
|
-
|
27
|
-
|
28
|
-
## Rails 6.1.2 (February 09, 2021) ##
|
29
|
-
|
30
|
-
* No changes.
|
31
|
-
|
32
|
-
|
33
|
-
## Rails 6.1.1 (January 07, 2021) ##
|
34
|
-
|
35
|
-
* No changes.
|
36
|
-
|
37
|
-
|
38
|
-
## Rails 6.1.0 (December 09, 2020) ##
|
39
|
-
|
40
|
-
* `ActionCable::Connection::Base` now allows intercepting unhandled exceptions
|
41
|
-
with `rescue_from` before they are logged, which is useful for error reporting
|
42
|
-
tools and other integrations.
|
43
|
-
|
44
|
-
*Justin Talbott*
|
45
|
-
|
46
|
-
* Add `ActionCable::Channel#stream_or_reject_for` to stream if record is present, otherwise reject the connection
|
47
|
-
|
48
|
-
*Atul Bhosale*
|
49
|
-
|
50
|
-
* Add `ActionCable::Channel#stop_stream_from` and `#stop_stream_for` to unsubscribe from a specific stream.
|
51
|
-
|
52
|
-
*Zhang Kang*
|
53
|
-
|
54
|
-
* Add PostgreSQL subscription connection identificator.
|
55
|
-
|
56
|
-
Now you can distinguish Action Cable PostgreSQL subscription connections among others.
|
57
|
-
Also, you can set custom `id` in `cable.yml` configuration.
|
58
|
-
|
59
|
-
```sql
|
60
|
-
SELECT application_name FROM pg_stat_activity;
|
61
|
-
/*
|
62
|
-
application_name
|
63
|
-
------------------------
|
64
|
-
psql
|
65
|
-
ActionCable-PID-42
|
66
|
-
(2 rows)
|
67
|
-
*/
|
68
|
-
```
|
69
|
-
|
70
|
-
*Sergey Ponomarev*
|
71
|
-
|
72
|
-
* Subscription confirmations and rejections are now logged at the `DEBUG` level instead of `INFO`.
|
73
|
-
|
74
|
-
*DHH*
|
75
|
-
|
76
|
-
|
77
|
-
Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/actioncable/CHANGELOG.md) for previous changes.
|