@rails/actioncable 6.0.2 → 7.1.2

Sign up to get free protection for your applications and to get access to all the features.
package/src/consumer.js CHANGED
@@ -6,7 +6,7 @@ import Subscriptions from "./subscriptions"
6
6
  // The Consumer instance is also the gateway to establishing subscriptions to desired channels through the #createSubscription
7
7
  // method.
8
8
  //
9
- // The following example shows how this can be setup:
9
+ // The following example shows how this can be set up:
10
10
  //
11
11
  // App = {}
12
12
  // App.cable = ActionCable.createConsumer("ws://example.com/accounts/1")
@@ -32,6 +32,7 @@ export default class Consumer {
32
32
  this._url = url
33
33
  this.subscriptions = new Subscriptions(this)
34
34
  this.connection = new Connection(this)
35
+ this.subprotocols = []
35
36
  }
36
37
 
37
38
  get url() {
@@ -55,6 +56,10 @@ export default class Consumer {
55
56
  return this.connection.open()
56
57
  }
57
58
  }
59
+
60
+ addSubProtocol(subprotocol) {
61
+ this.subprotocols = [...this.subprotocols, subprotocol]
62
+ }
58
63
  }
59
64
 
60
65
  export function createWebSocketURL(url) {
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,2 @@
1
+ export * from "./index"
2
+ console.log("DEPRECATION: action_cable.js has been renamed to actioncable.js – please update your reference before Rails 8")
@@ -0,0 +1,20 @@
1
+ export default {
2
+ "message_types": {
3
+ "welcome": "welcome",
4
+ "disconnect": "disconnect",
5
+ "ping": "ping",
6
+ "confirmation": "confirm_subscription",
7
+ "rejection": "reject_subscription"
8
+ },
9
+ "disconnect_reasons": {
10
+ "unauthorized": "unauthorized",
11
+ "invalid_request": "invalid_request",
12
+ "server_restart": "server_restart",
13
+ "remote": "remote"
14
+ },
15
+ "default_mount_path": "/cable",
16
+ "protocols": [
17
+ "actioncable-v1-json",
18
+ "actioncable-unsupported"
19
+ ]
20
+ }
package/src/logger.js CHANGED
@@ -1,5 +1,17 @@
1
1
  import adapters from "./adapters"
2
2
 
3
+ // The logger is disabled by default. You can enable it with:
4
+ //
5
+ // ActionCable.logger.enabled = true
6
+ //
7
+ // Example:
8
+ //
9
+ // import * as ActionCable from '@rails/actioncable'
10
+ //
11
+ // ActionCable.logger.enabled = true
12
+ // ActionCable.logger.log('Connection Established.')
13
+ //
14
+
3
15
  export default {
4
16
  log(...messages) {
5
17
  if (this.enabled) {
@@ -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
@@ -1,7 +1,10 @@
1
1
  import Subscription from "./subscription"
2
+ import SubscriptionGuarantor from "./subscription_guarantor"
3
+ import logger from "./logger"
2
4
 
3
- // Collection class for creating (and internally managing) channel subscriptions. The only method intended to be triggered by the user
4
- // us ActionCable.Subscriptions#create, and it should be called through the consumer like so:
5
+ // Collection class for creating (and internally managing) channel subscriptions.
6
+ // The only method intended to be triggered by the user is ActionCable.Subscriptions#create,
7
+ // and it should be called through the consumer like so:
5
8
  //
6
9
  // App = {}
7
10
  // App.cable = ActionCable.createConsumer("ws://example.com/accounts/1")
@@ -12,6 +15,7 @@ import Subscription from "./subscription"
12
15
  export default class Subscriptions {
13
16
  constructor(consumer) {
14
17
  this.consumer = consumer
18
+ this.guarantor = new SubscriptionGuarantor(this)
15
19
  this.subscriptions = []
16
20
  }
17
21
 
@@ -28,7 +32,7 @@ export default class Subscriptions {
28
32
  this.subscriptions.push(subscription)
29
33
  this.consumer.ensureActiveConnection()
30
34
  this.notify(subscription, "initialized")
31
- this.sendCommand(subscription, "subscribe")
35
+ this.subscribe(subscription)
32
36
  return subscription
33
37
  }
34
38
 
@@ -49,6 +53,7 @@ export default class Subscriptions {
49
53
  }
50
54
 
51
55
  forget(subscription) {
56
+ this.guarantor.forget(subscription)
52
57
  this.subscriptions = (this.subscriptions.filter((s) => s !== subscription))
53
58
  return subscription
54
59
  }
@@ -59,7 +64,7 @@ export default class Subscriptions {
59
64
 
60
65
  reload() {
61
66
  return this.subscriptions.map((subscription) =>
62
- this.sendCommand(subscription, "subscribe"))
67
+ this.subscribe(subscription))
63
68
  }
64
69
 
65
70
  notifyAll(callbackName, ...args) {
@@ -79,6 +84,18 @@ export default class Subscriptions {
79
84
  (typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined))
80
85
  }
81
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
+
82
99
  sendCommand(subscription, command) {
83
100
  const {identifier} = subscription
84
101
  return this.consumer.send({command, identifier})
package/CHANGELOG.md DELETED
@@ -1,179 +0,0 @@
1
- ## Rails 6.0.2 (December 13, 2019) ##
2
-
3
- * No changes.
4
-
5
-
6
- ## Rails 6.0.1 (November 5, 2019) ##
7
-
8
- * No changes.
9
-
10
-
11
- ## Rails 6.0.0 (August 16, 2019) ##
12
-
13
- * No changes.
14
-
15
-
16
- ## Rails 6.0.0.rc2 (July 22, 2019) ##
17
-
18
- * No changes.
19
-
20
-
21
- ## Rails 6.0.0.rc1 (April 24, 2019) ##
22
-
23
- * No changes.
24
-
25
-
26
- ## Rails 6.0.0.beta3 (March 11, 2019) ##
27
-
28
- * No changes.
29
-
30
-
31
- ## Rails 6.0.0.beta2 (February 25, 2019) ##
32
-
33
- * PostgreSQL subscription adapters now support `channel_prefix` option in cable.yml
34
-
35
- Avoids channel name collisions when multiple apps use the same database for Action Cable.
36
-
37
- *Vladimir Dementyev*
38
-
39
- * Allow passing custom configuration to `ActionCable::Server::Base`.
40
-
41
- You can now create a standalone Action Cable server with a custom configuration
42
- (e.g. to run it in isolation from the default one):
43
-
44
- ```ruby
45
- config = ActionCable::Server::Configuration.new
46
- config.cable = { adapter: "redis", channel_prefix: "custom_" }
47
-
48
- CUSTOM_CABLE = ActionCable::Server::Base.new(config: config)
49
- ```
50
-
51
- Then you can mount it in the `routes.rb` file:
52
-
53
- ```ruby
54
- Rails.application.routes.draw do
55
- mount CUSTOM_CABLE => "/custom_cable"
56
- # ...
57
- end
58
- ```
59
-
60
- *Vladimir Dementyev*
61
-
62
- * Add `:action_cable_connection` and `:action_cable_channel` load hooks.
63
-
64
- You can use them to extend `ActionCable::Connection::Base` and `ActionCable::Channel::Base`
65
- functionality:
66
-
67
- ```ruby
68
- ActiveSupport.on_load(:action_cable_channel) do
69
- # do something in the context of ActionCable::Channel::Base
70
- end
71
- ```
72
-
73
- *Vladimir Dementyev*
74
-
75
- * Add `Channel::Base#broadcast_to`.
76
-
77
- You can now call `broadcast_to` within a channel action, which equals to
78
- the `self.class.broadcast_to`.
79
-
80
- *Vladimir Dementyev*
81
-
82
- * Make `Channel::Base.broadcasting_for` a public API.
83
-
84
- You can use `.broadcasting_for` to generate a unique stream identifier within
85
- a channel for the specified target (e.g. Active Record model):
86
-
87
- ```ruby
88
- ChatChannel.broadcasting_for(model) # => "chat:<model.to_gid_param>"
89
- ```
90
-
91
- *Vladimir Dementyev*
92
-
93
-
94
- ## Rails 6.0.0.beta1 (January 18, 2019) ##
95
-
96
- * [Rename npm package](https://github.com/rails/rails/pull/34905) from
97
- [`actioncable`](https://www.npmjs.com/package/actioncable) to
98
- [`@rails/actioncable`](https://www.npmjs.com/package/@rails/actioncable).
99
-
100
- *Javan Makhmali*
101
-
102
- * Merge [`action-cable-testing`](https://github.com/palkan/action-cable-testing) to Rails.
103
-
104
- *Vladimir Dementyev*
105
-
106
- * The JavaScript WebSocket client will no longer try to reconnect
107
- when you call `reject_unauthorized_connection` on the connection.
108
-
109
- *Mick Staugaard*
110
-
111
- * `ActionCable.Connection#getState` now references the configurable
112
- `ActionCable.adapters.WebSocket` property rather than the `WebSocket` global
113
- variable, matching the behavior of `ActionCable.Connection#open`.
114
-
115
- *Richard Macklin*
116
-
117
- * The ActionCable javascript package has been converted from CoffeeScript
118
- to ES2015, and we now publish the source code in the npm distribution.
119
-
120
- This allows ActionCable users to depend on the javascript source code
121
- rather than the compiled code, which can produce smaller javascript bundles.
122
-
123
- This change includes some breaking changes to optional parts of the
124
- ActionCable javascript API:
125
-
126
- - Configuration of the WebSocket adapter and logger adapter have been moved
127
- from properties of `ActionCable` to properties of `ActionCable.adapters`.
128
- If you are currently configuring these adapters you will need to make
129
- these changes when upgrading:
130
-
131
- ```diff
132
- - ActionCable.WebSocket = MyWebSocket
133
- + ActionCable.adapters.WebSocket = MyWebSocket
134
- ```
135
- ```diff
136
- - ActionCable.logger = myLogger
137
- + ActionCable.adapters.logger = myLogger
138
- ```
139
-
140
- - The `ActionCable.startDebugging()` and `ActionCable.stopDebugging()`
141
- methods have been removed and replaced with the property
142
- `ActionCable.logger.enabled`. If you are currently using these methods you
143
- will need to make these changes when upgrading:
144
-
145
- ```diff
146
- - ActionCable.startDebugging()
147
- + ActionCable.logger.enabled = true
148
- ```
149
- ```diff
150
- - ActionCable.stopDebugging()
151
- + ActionCable.logger.enabled = false
152
- ```
153
-
154
- *Richard Macklin*
155
-
156
- * Add `id` option to redis adapter so now you can distinguish
157
- ActionCable's redis connections among others. Also, you can set
158
- custom id in options.
159
-
160
- Before:
161
- ```
162
- $ redis-cli client list
163
- id=669 addr=127.0.0.1:46442 fd=8 name= age=18 ...
164
- ```
165
-
166
- After:
167
- ```
168
- $ redis-cli client list
169
- id=673 addr=127.0.0.1:46516 fd=8 name=ActionCable-PID-19413 age=2 ...
170
- ```
171
-
172
- *Ilia Kasianenko*
173
-
174
- * Rails 6 requires Ruby 2.5.0 or newer.
175
-
176
- *Jeremy Daer*, *Kasper Timm Hansen*
177
-
178
-
179
- Please check [5-2-stable](https://github.com/rails/rails/blob/5-2-stable/actioncable/CHANGELOG.md) for previous changes.