actioncable 6.1.7.9 → 7.2.2.1
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/CHANGELOG.md +33 -160
- data/MIT-LICENSE +1 -1
- data/README.md +5 -5
- data/app/assets/javascripts/action_cable.js +239 -302
- data/app/assets/javascripts/actioncable.esm.js +512 -0
- data/app/assets/javascripts/actioncable.js +510 -0
- data/lib/action_cable/channel/base.rb +114 -90
- data/lib/action_cable/channel/broadcasting.rb +25 -16
- data/lib/action_cable/channel/callbacks.rb +39 -0
- data/lib/action_cable/channel/naming.rb +10 -7
- data/lib/action_cable/channel/periodic_timers.rb +7 -7
- data/lib/action_cable/channel/streams.rb +81 -68
- data/lib/action_cable/channel/test_case.rb +133 -87
- data/lib/action_cable/connection/authorization.rb +4 -1
- data/lib/action_cable/connection/base.rb +71 -43
- data/lib/action_cable/connection/callbacks.rb +57 -0
- data/lib/action_cable/connection/client_socket.rb +3 -1
- data/lib/action_cable/connection/identification.rb +10 -6
- data/lib/action_cable/connection/internal_channel.rb +7 -2
- data/lib/action_cable/connection/message_buffer.rb +4 -1
- data/lib/action_cable/connection/stream.rb +2 -2
- data/lib/action_cable/connection/stream_event_loop.rb +4 -4
- data/lib/action_cable/connection/subscriptions.rb +8 -3
- data/lib/action_cable/connection/tagged_logger_proxy.rb +14 -9
- data/lib/action_cable/connection/test_case.rb +67 -55
- data/lib/action_cable/connection/web_socket.rb +11 -7
- data/lib/action_cable/deprecator.rb +9 -0
- data/lib/action_cable/engine.rb +28 -9
- data/lib/action_cable/gem_version.rb +7 -5
- data/lib/action_cable/helpers/action_cable_helper.rb +21 -18
- data/lib/action_cable/remote_connections.rb +25 -13
- data/lib/action_cable/server/base.rb +29 -14
- data/lib/action_cable/server/broadcasting.rb +24 -16
- data/lib/action_cable/server/configuration.rb +28 -14
- data/lib/action_cable/server/connections.rb +13 -5
- data/lib/action_cable/server/worker/active_record_connection_management.rb +4 -2
- data/lib/action_cable/server/worker.rb +7 -7
- data/lib/action_cable/subscription_adapter/async.rb +1 -1
- data/lib/action_cable/subscription_adapter/base.rb +2 -0
- data/lib/action_cable/subscription_adapter/channel_prefix.rb +2 -0
- data/lib/action_cable/subscription_adapter/inline.rb +2 -0
- data/lib/action_cable/subscription_adapter/postgresql.rb +6 -5
- data/lib/action_cable/subscription_adapter/redis.rb +101 -25
- data/lib/action_cable/subscription_adapter/subscriber_map.rb +2 -0
- data/lib/action_cable/subscription_adapter/test.rb +7 -6
- data/lib/action_cable/test_case.rb +2 -0
- data/lib/action_cable/test_helper.rb +89 -59
- data/lib/action_cable/version.rb +3 -1
- data/lib/action_cable.rb +30 -12
- data/lib/rails/generators/channel/USAGE +14 -8
- data/lib/rails/generators/channel/channel_generator.rb +95 -20
- data/lib/rails/generators/channel/templates/javascript/index.js.tt +1 -5
- data/lib/rails/generators/test_unit/channel_generator.rb +2 -0
- metadata +29 -15
- data/lib/action_cable/channel.rb +0 -17
- data/lib/action_cable/connection.rb +0 -22
- data/lib/action_cable/server.rb +0 -16
- data/lib/action_cable/subscription_adapter.rb +0 -12
@@ -1,154 +1,114 @@
|
|
1
1
|
(function(global, factory) {
|
2
|
-
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) :
|
3
|
-
|
2
|
+
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self,
|
3
|
+
factory(global.ActionCable = {}));
|
4
|
+
})(this, (function(exports) {
|
4
5
|
"use strict";
|
5
6
|
var adapters = {
|
6
|
-
logger:
|
7
|
-
WebSocket:
|
7
|
+
logger: typeof console !== "undefined" ? console : undefined,
|
8
|
+
WebSocket: typeof WebSocket !== "undefined" ? WebSocket : undefined
|
8
9
|
};
|
9
10
|
var logger = {
|
10
|
-
log
|
11
|
+
log(...messages) {
|
11
12
|
if (this.enabled) {
|
12
|
-
var _adapters$logger;
|
13
|
-
for (var _len = arguments.length, messages = Array(_len), _key = 0; _key < _len; _key++) {
|
14
|
-
messages[_key] = arguments[_key];
|
15
|
-
}
|
16
13
|
messages.push(Date.now());
|
17
|
-
|
18
|
-
}
|
19
|
-
}
|
20
|
-
};
|
21
|
-
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
|
22
|
-
return typeof obj;
|
23
|
-
} : function(obj) {
|
24
|
-
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
25
|
-
};
|
26
|
-
var classCallCheck = function(instance, Constructor) {
|
27
|
-
if (!(instance instanceof Constructor)) {
|
28
|
-
throw new TypeError("Cannot call a class as a function");
|
29
|
-
}
|
30
|
-
};
|
31
|
-
var createClass = function() {
|
32
|
-
function defineProperties(target, props) {
|
33
|
-
for (var i = 0; i < props.length; i++) {
|
34
|
-
var descriptor = props[i];
|
35
|
-
descriptor.enumerable = descriptor.enumerable || false;
|
36
|
-
descriptor.configurable = true;
|
37
|
-
if ("value" in descriptor) descriptor.writable = true;
|
38
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
14
|
+
adapters.logger.log("[ActionCable]", ...messages);
|
39
15
|
}
|
40
16
|
}
|
41
|
-
return function(Constructor, protoProps, staticProps) {
|
42
|
-
if (protoProps) defineProperties(Constructor.prototype, protoProps);
|
43
|
-
if (staticProps) defineProperties(Constructor, staticProps);
|
44
|
-
return Constructor;
|
45
|
-
};
|
46
|
-
}();
|
47
|
-
var now = function now() {
|
48
|
-
return new Date().getTime();
|
49
|
-
};
|
50
|
-
var secondsSince = function secondsSince(time) {
|
51
|
-
return (now() - time) / 1e3;
|
52
|
-
};
|
53
|
-
var clamp = function clamp(number, min, max) {
|
54
|
-
return Math.max(min, Math.min(max, number));
|
55
17
|
};
|
56
|
-
|
57
|
-
|
58
|
-
|
18
|
+
const now = () => (new Date).getTime();
|
19
|
+
const secondsSince = time => (now() - time) / 1e3;
|
20
|
+
class ConnectionMonitor {
|
21
|
+
constructor(connection) {
|
59
22
|
this.visibilityDidChange = this.visibilityDidChange.bind(this);
|
60
23
|
this.connection = connection;
|
61
24
|
this.reconnectAttempts = 0;
|
62
25
|
}
|
63
|
-
|
26
|
+
start() {
|
64
27
|
if (!this.isRunning()) {
|
65
28
|
this.startedAt = now();
|
66
29
|
delete this.stoppedAt;
|
67
30
|
this.startPolling();
|
68
31
|
addEventListener("visibilitychange", this.visibilityDidChange);
|
69
|
-
logger.log(
|
32
|
+
logger.log(`ConnectionMonitor started. stale threshold = ${this.constructor.staleThreshold} s`);
|
70
33
|
}
|
71
|
-
}
|
72
|
-
|
34
|
+
}
|
35
|
+
stop() {
|
73
36
|
if (this.isRunning()) {
|
74
37
|
this.stoppedAt = now();
|
75
38
|
this.stopPolling();
|
76
39
|
removeEventListener("visibilitychange", this.visibilityDidChange);
|
77
40
|
logger.log("ConnectionMonitor stopped");
|
78
41
|
}
|
79
|
-
}
|
80
|
-
|
42
|
+
}
|
43
|
+
isRunning() {
|
81
44
|
return this.startedAt && !this.stoppedAt;
|
82
|
-
}
|
83
|
-
|
45
|
+
}
|
46
|
+
recordMessage() {
|
84
47
|
this.pingedAt = now();
|
85
|
-
}
|
86
|
-
|
48
|
+
}
|
49
|
+
recordConnect() {
|
87
50
|
this.reconnectAttempts = 0;
|
88
|
-
this.recordPing();
|
89
51
|
delete this.disconnectedAt;
|
90
52
|
logger.log("ConnectionMonitor recorded connect");
|
91
|
-
}
|
92
|
-
|
53
|
+
}
|
54
|
+
recordDisconnect() {
|
93
55
|
this.disconnectedAt = now();
|
94
56
|
logger.log("ConnectionMonitor recorded disconnect");
|
95
|
-
}
|
96
|
-
|
57
|
+
}
|
58
|
+
startPolling() {
|
97
59
|
this.stopPolling();
|
98
60
|
this.poll();
|
99
|
-
}
|
100
|
-
|
61
|
+
}
|
62
|
+
stopPolling() {
|
101
63
|
clearTimeout(this.pollTimeout);
|
102
|
-
}
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
64
|
+
}
|
65
|
+
poll() {
|
66
|
+
this.pollTimeout = setTimeout((() => {
|
67
|
+
this.reconnectIfStale();
|
68
|
+
this.poll();
|
69
|
+
}), this.getPollInterval());
|
70
|
+
}
|
71
|
+
getPollInterval() {
|
72
|
+
const {staleThreshold: staleThreshold, reconnectionBackoffRate: reconnectionBackoffRate} = this.constructor;
|
73
|
+
const backoff = Math.pow(1 + reconnectionBackoffRate, Math.min(this.reconnectAttempts, 10));
|
74
|
+
const jitterMax = this.reconnectAttempts === 0 ? 1 : reconnectionBackoffRate;
|
75
|
+
const jitter = jitterMax * Math.random();
|
76
|
+
return staleThreshold * 1e3 * backoff * (1 + jitter);
|
77
|
+
}
|
78
|
+
reconnectIfStale() {
|
116
79
|
if (this.connectionIsStale()) {
|
117
|
-
logger.log(
|
80
|
+
logger.log(`ConnectionMonitor detected stale connection. reconnectAttempts = ${this.reconnectAttempts}, time stale = ${secondsSince(this.refreshedAt)} s, stale threshold = ${this.constructor.staleThreshold} s`);
|
118
81
|
this.reconnectAttempts++;
|
119
82
|
if (this.disconnectedRecently()) {
|
120
|
-
logger.log(
|
83
|
+
logger.log(`ConnectionMonitor skipping reopening recent disconnect. time disconnected = ${secondsSince(this.disconnectedAt)} s`);
|
121
84
|
} else {
|
122
85
|
logger.log("ConnectionMonitor reopening");
|
123
86
|
this.connection.reopen();
|
124
87
|
}
|
125
88
|
}
|
126
|
-
}
|
127
|
-
|
128
|
-
return
|
129
|
-
}
|
130
|
-
|
89
|
+
}
|
90
|
+
get refreshedAt() {
|
91
|
+
return this.pingedAt ? this.pingedAt : this.startedAt;
|
92
|
+
}
|
93
|
+
connectionIsStale() {
|
94
|
+
return secondsSince(this.refreshedAt) > this.constructor.staleThreshold;
|
95
|
+
}
|
96
|
+
disconnectedRecently() {
|
131
97
|
return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold;
|
132
|
-
}
|
133
|
-
|
134
|
-
var _this2 = this;
|
98
|
+
}
|
99
|
+
visibilityDidChange() {
|
135
100
|
if (document.visibilityState === "visible") {
|
136
|
-
setTimeout(
|
137
|
-
if (
|
138
|
-
logger.log(
|
139
|
-
|
101
|
+
setTimeout((() => {
|
102
|
+
if (this.connectionIsStale() || !this.connection.isOpen()) {
|
103
|
+
logger.log(`ConnectionMonitor reopening stale connection on visibilitychange. visibilityState = ${document.visibilityState}`);
|
104
|
+
this.connection.reopen();
|
140
105
|
}
|
141
|
-
}, 200);
|
106
|
+
}), 200);
|
142
107
|
}
|
143
|
-
}
|
144
|
-
|
145
|
-
}();
|
146
|
-
ConnectionMonitor.pollInterval = {
|
147
|
-
min: 3,
|
148
|
-
max: 30,
|
149
|
-
multiplier: 5
|
150
|
-
};
|
108
|
+
}
|
109
|
+
}
|
151
110
|
ConnectionMonitor.staleThreshold = 6;
|
111
|
+
ConnectionMonitor.reconnectionBackoffRate = .15;
|
152
112
|
var INTERNAL = {
|
153
113
|
message_types: {
|
154
114
|
welcome: "welcome",
|
@@ -160,139 +120,151 @@
|
|
160
120
|
disconnect_reasons: {
|
161
121
|
unauthorized: "unauthorized",
|
162
122
|
invalid_request: "invalid_request",
|
163
|
-
server_restart: "server_restart"
|
123
|
+
server_restart: "server_restart",
|
124
|
+
remote: "remote"
|
164
125
|
},
|
165
126
|
default_mount_path: "/cable",
|
166
127
|
protocols: [ "actioncable-v1-json", "actioncable-unsupported" ]
|
167
128
|
};
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
classCallCheck(this, Connection);
|
129
|
+
const {message_types: message_types, protocols: protocols} = INTERNAL;
|
130
|
+
const supportedProtocols = protocols.slice(0, protocols.length - 1);
|
131
|
+
const indexOf = [].indexOf;
|
132
|
+
class Connection {
|
133
|
+
constructor(consumer) {
|
174
134
|
this.open = this.open.bind(this);
|
175
135
|
this.consumer = consumer;
|
176
136
|
this.subscriptions = this.consumer.subscriptions;
|
177
137
|
this.monitor = new ConnectionMonitor(this);
|
178
138
|
this.disconnected = true;
|
179
139
|
}
|
180
|
-
|
140
|
+
send(data) {
|
181
141
|
if (this.isOpen()) {
|
182
142
|
this.webSocket.send(JSON.stringify(data));
|
183
143
|
return true;
|
184
144
|
} else {
|
185
145
|
return false;
|
186
146
|
}
|
187
|
-
}
|
188
|
-
|
147
|
+
}
|
148
|
+
open() {
|
189
149
|
if (this.isActive()) {
|
190
|
-
logger.log(
|
150
|
+
logger.log(`Attempted to open WebSocket, but existing socket is ${this.getState()}`);
|
191
151
|
return false;
|
192
152
|
} else {
|
193
|
-
|
153
|
+
const socketProtocols = [ ...protocols, ...this.consumer.subprotocols || [] ];
|
154
|
+
logger.log(`Opening WebSocket, current state is ${this.getState()}, subprotocols: ${socketProtocols}`);
|
194
155
|
if (this.webSocket) {
|
195
156
|
this.uninstallEventHandlers();
|
196
157
|
}
|
197
|
-
this.webSocket = new adapters.WebSocket(this.consumer.url,
|
158
|
+
this.webSocket = new adapters.WebSocket(this.consumer.url, socketProtocols);
|
198
159
|
this.installEventHandlers();
|
199
160
|
this.monitor.start();
|
200
161
|
return true;
|
201
162
|
}
|
202
|
-
}
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
}, allowReconnect = _ref.allowReconnect;
|
163
|
+
}
|
164
|
+
close({allowReconnect: allowReconnect} = {
|
165
|
+
allowReconnect: true
|
166
|
+
}) {
|
207
167
|
if (!allowReconnect) {
|
208
168
|
this.monitor.stop();
|
209
169
|
}
|
210
|
-
if (this.
|
170
|
+
if (this.isOpen()) {
|
211
171
|
return this.webSocket.close();
|
212
172
|
}
|
213
|
-
}
|
214
|
-
|
215
|
-
logger.log(
|
173
|
+
}
|
174
|
+
reopen() {
|
175
|
+
logger.log(`Reopening WebSocket, current state is ${this.getState()}`);
|
216
176
|
if (this.isActive()) {
|
217
177
|
try {
|
218
178
|
return this.close();
|
219
179
|
} catch (error) {
|
220
180
|
logger.log("Failed to reopen WebSocket", error);
|
221
181
|
} finally {
|
222
|
-
logger.log(
|
182
|
+
logger.log(`Reopening WebSocket in ${this.constructor.reopenDelay}ms`);
|
223
183
|
setTimeout(this.open, this.constructor.reopenDelay);
|
224
184
|
}
|
225
185
|
} else {
|
226
186
|
return this.open();
|
227
187
|
}
|
228
|
-
}
|
229
|
-
|
188
|
+
}
|
189
|
+
getProtocol() {
|
230
190
|
if (this.webSocket) {
|
231
191
|
return this.webSocket.protocol;
|
232
192
|
}
|
233
|
-
}
|
234
|
-
|
193
|
+
}
|
194
|
+
isOpen() {
|
235
195
|
return this.isState("open");
|
236
|
-
}
|
237
|
-
|
196
|
+
}
|
197
|
+
isActive() {
|
238
198
|
return this.isState("open", "connecting");
|
239
|
-
}
|
240
|
-
|
199
|
+
}
|
200
|
+
triedToReconnect() {
|
201
|
+
return this.monitor.reconnectAttempts > 0;
|
202
|
+
}
|
203
|
+
isProtocolSupported() {
|
241
204
|
return indexOf.call(supportedProtocols, this.getProtocol()) >= 0;
|
242
|
-
}
|
243
|
-
|
244
|
-
for (var _len = arguments.length, states = Array(_len), _key = 0; _key < _len; _key++) {
|
245
|
-
states[_key] = arguments[_key];
|
246
|
-
}
|
205
|
+
}
|
206
|
+
isState(...states) {
|
247
207
|
return indexOf.call(states, this.getState()) >= 0;
|
248
|
-
}
|
249
|
-
|
208
|
+
}
|
209
|
+
getState() {
|
250
210
|
if (this.webSocket) {
|
251
|
-
for (
|
211
|
+
for (let state in adapters.WebSocket) {
|
252
212
|
if (adapters.WebSocket[state] === this.webSocket.readyState) {
|
253
213
|
return state.toLowerCase();
|
254
214
|
}
|
255
215
|
}
|
256
216
|
}
|
257
217
|
return null;
|
258
|
-
}
|
259
|
-
|
260
|
-
for (
|
261
|
-
|
262
|
-
this.webSocket[
|
218
|
+
}
|
219
|
+
installEventHandlers() {
|
220
|
+
for (let eventName in this.events) {
|
221
|
+
const handler = this.events[eventName].bind(this);
|
222
|
+
this.webSocket[`on${eventName}`] = handler;
|
263
223
|
}
|
264
|
-
}
|
265
|
-
|
266
|
-
for (
|
267
|
-
this.webSocket[
|
224
|
+
}
|
225
|
+
uninstallEventHandlers() {
|
226
|
+
for (let eventName in this.events) {
|
227
|
+
this.webSocket[`on${eventName}`] = function() {};
|
268
228
|
}
|
269
|
-
}
|
270
|
-
|
271
|
-
}();
|
229
|
+
}
|
230
|
+
}
|
272
231
|
Connection.reopenDelay = 500;
|
273
232
|
Connection.prototype.events = {
|
274
|
-
message
|
233
|
+
message(event) {
|
275
234
|
if (!this.isProtocolSupported()) {
|
276
235
|
return;
|
277
236
|
}
|
278
|
-
|
237
|
+
const {identifier: identifier, message: message, reason: reason, reconnect: reconnect, type: type} = JSON.parse(event.data);
|
238
|
+
this.monitor.recordMessage();
|
279
239
|
switch (type) {
|
280
240
|
case message_types.welcome:
|
241
|
+
if (this.triedToReconnect()) {
|
242
|
+
this.reconnectAttempted = true;
|
243
|
+
}
|
281
244
|
this.monitor.recordConnect();
|
282
245
|
return this.subscriptions.reload();
|
283
246
|
|
284
247
|
case message_types.disconnect:
|
285
|
-
logger.log(
|
248
|
+
logger.log(`Disconnecting. Reason: ${reason}`);
|
286
249
|
return this.close({
|
287
250
|
allowReconnect: reconnect
|
288
251
|
});
|
289
252
|
|
290
253
|
case message_types.ping:
|
291
|
-
return
|
254
|
+
return null;
|
292
255
|
|
293
256
|
case message_types.confirmation:
|
294
257
|
this.subscriptions.confirmSubscription(identifier);
|
295
|
-
|
258
|
+
if (this.reconnectAttempted) {
|
259
|
+
this.reconnectAttempted = false;
|
260
|
+
return this.subscriptions.notify(identifier, "connected", {
|
261
|
+
reconnected: true
|
262
|
+
});
|
263
|
+
} else {
|
264
|
+
return this.subscriptions.notify(identifier, "connected", {
|
265
|
+
reconnected: false
|
266
|
+
});
|
267
|
+
}
|
296
268
|
|
297
269
|
case message_types.rejection:
|
298
270
|
return this.subscriptions.reject(identifier);
|
@@ -301,8 +273,8 @@
|
|
301
273
|
return this.subscriptions.notify(identifier, "received", message);
|
302
274
|
}
|
303
275
|
},
|
304
|
-
open
|
305
|
-
logger.log(
|
276
|
+
open() {
|
277
|
+
logger.log(`WebSocket onopen event, using '${this.getProtocol()}' subprotocol`);
|
306
278
|
this.disconnected = false;
|
307
279
|
if (!this.isProtocolSupported()) {
|
308
280
|
logger.log("Protocol is unsupported. Stopping monitor and disconnecting.");
|
@@ -311,7 +283,7 @@
|
|
311
283
|
});
|
312
284
|
}
|
313
285
|
},
|
314
|
-
close
|
286
|
+
close(event) {
|
315
287
|
logger.log("WebSocket onclose event");
|
316
288
|
if (this.disconnected) {
|
317
289
|
return;
|
@@ -322,222 +294,187 @@
|
|
322
294
|
willAttemptReconnect: this.monitor.isRunning()
|
323
295
|
});
|
324
296
|
},
|
325
|
-
error
|
297
|
+
error() {
|
326
298
|
logger.log("WebSocket onerror event");
|
327
299
|
}
|
328
300
|
};
|
329
|
-
|
301
|
+
const extend = function(object, properties) {
|
330
302
|
if (properties != null) {
|
331
|
-
for (
|
332
|
-
|
303
|
+
for (let key in properties) {
|
304
|
+
const value = properties[key];
|
333
305
|
object[key] = value;
|
334
306
|
}
|
335
307
|
}
|
336
308
|
return object;
|
337
309
|
};
|
338
|
-
|
339
|
-
|
340
|
-
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
341
|
-
var mixin = arguments[2];
|
342
|
-
classCallCheck(this, Subscription);
|
310
|
+
class Subscription {
|
311
|
+
constructor(consumer, params = {}, mixin) {
|
343
312
|
this.consumer = consumer;
|
344
313
|
this.identifier = JSON.stringify(params);
|
345
314
|
extend(this, mixin);
|
346
315
|
}
|
347
|
-
|
348
|
-
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
316
|
+
perform(action, data = {}) {
|
349
317
|
data.action = action;
|
350
318
|
return this.send(data);
|
351
|
-
}
|
352
|
-
|
319
|
+
}
|
320
|
+
send(data) {
|
353
321
|
return this.consumer.send({
|
354
322
|
command: "message",
|
355
323
|
identifier: this.identifier,
|
356
324
|
data: JSON.stringify(data)
|
357
325
|
});
|
358
|
-
}
|
359
|
-
|
326
|
+
}
|
327
|
+
unsubscribe() {
|
360
328
|
return this.consumer.subscriptions.remove(this);
|
361
|
-
}
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
function SubscriptionGuarantor(subscriptions) {
|
366
|
-
classCallCheck(this, SubscriptionGuarantor);
|
329
|
+
}
|
330
|
+
}
|
331
|
+
class SubscriptionGuarantor {
|
332
|
+
constructor(subscriptions) {
|
367
333
|
this.subscriptions = subscriptions;
|
368
334
|
this.pendingSubscriptions = [];
|
369
335
|
}
|
370
|
-
|
336
|
+
guarantee(subscription) {
|
371
337
|
if (this.pendingSubscriptions.indexOf(subscription) == -1) {
|
372
|
-
logger.log(
|
338
|
+
logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`);
|
373
339
|
this.pendingSubscriptions.push(subscription);
|
374
340
|
} else {
|
375
|
-
logger.log(
|
341
|
+
logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`);
|
376
342
|
}
|
377
343
|
this.startGuaranteeing();
|
378
|
-
}
|
379
|
-
|
380
|
-
logger.log(
|
381
|
-
this.pendingSubscriptions = this.pendingSubscriptions.filter(
|
382
|
-
|
383
|
-
|
384
|
-
};
|
385
|
-
SubscriptionGuarantor.prototype.startGuaranteeing = function startGuaranteeing() {
|
344
|
+
}
|
345
|
+
forget(subscription) {
|
346
|
+
logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`);
|
347
|
+
this.pendingSubscriptions = this.pendingSubscriptions.filter((s => s !== subscription));
|
348
|
+
}
|
349
|
+
startGuaranteeing() {
|
386
350
|
this.stopGuaranteeing();
|
387
351
|
this.retrySubscribing();
|
388
|
-
}
|
389
|
-
|
352
|
+
}
|
353
|
+
stopGuaranteeing() {
|
390
354
|
clearTimeout(this.retryTimeout);
|
391
|
-
}
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
});
|
355
|
+
}
|
356
|
+
retrySubscribing() {
|
357
|
+
this.retryTimeout = setTimeout((() => {
|
358
|
+
if (this.subscriptions && typeof this.subscriptions.subscribe === "function") {
|
359
|
+
this.pendingSubscriptions.map((subscription => {
|
360
|
+
logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`);
|
361
|
+
this.subscriptions.subscribe(subscription);
|
362
|
+
}));
|
400
363
|
}
|
401
|
-
}, 500);
|
402
|
-
}
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
function Subscriptions(consumer) {
|
407
|
-
classCallCheck(this, Subscriptions);
|
364
|
+
}), 500);
|
365
|
+
}
|
366
|
+
}
|
367
|
+
class Subscriptions {
|
368
|
+
constructor(consumer) {
|
408
369
|
this.consumer = consumer;
|
409
370
|
this.guarantor = new SubscriptionGuarantor(this);
|
410
371
|
this.subscriptions = [];
|
411
372
|
}
|
412
|
-
|
413
|
-
|
414
|
-
|
373
|
+
create(channelName, mixin) {
|
374
|
+
const channel = channelName;
|
375
|
+
const params = typeof channel === "object" ? channel : {
|
415
376
|
channel: channel
|
416
377
|
};
|
417
|
-
|
378
|
+
const subscription = new Subscription(this.consumer, params, mixin);
|
418
379
|
return this.add(subscription);
|
419
|
-
}
|
420
|
-
|
380
|
+
}
|
381
|
+
add(subscription) {
|
421
382
|
this.subscriptions.push(subscription);
|
422
383
|
this.consumer.ensureActiveConnection();
|
423
384
|
this.notify(subscription, "initialized");
|
424
385
|
this.subscribe(subscription);
|
425
386
|
return subscription;
|
426
|
-
}
|
427
|
-
|
387
|
+
}
|
388
|
+
remove(subscription) {
|
428
389
|
this.forget(subscription);
|
429
390
|
if (!this.findAll(subscription.identifier).length) {
|
430
391
|
this.sendCommand(subscription, "unsubscribe");
|
431
392
|
}
|
432
393
|
return subscription;
|
433
|
-
}
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
_this.notify(subscription, "rejected");
|
394
|
+
}
|
395
|
+
reject(identifier) {
|
396
|
+
return this.findAll(identifier).map((subscription => {
|
397
|
+
this.forget(subscription);
|
398
|
+
this.notify(subscription, "rejected");
|
439
399
|
return subscription;
|
440
|
-
});
|
441
|
-
}
|
442
|
-
|
400
|
+
}));
|
401
|
+
}
|
402
|
+
forget(subscription) {
|
443
403
|
this.guarantor.forget(subscription);
|
444
|
-
this.subscriptions = this.subscriptions.filter(
|
445
|
-
return s !== subscription;
|
446
|
-
});
|
404
|
+
this.subscriptions = this.subscriptions.filter((s => s !== subscription));
|
447
405
|
return subscription;
|
448
|
-
}
|
449
|
-
|
450
|
-
return this.subscriptions.filter(
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
return this.subscriptions.map(
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
Subscriptions.prototype.notifyAll = function notifyAll(callbackName) {
|
461
|
-
var _this3 = this;
|
462
|
-
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
463
|
-
args[_key - 1] = arguments[_key];
|
464
|
-
}
|
465
|
-
return this.subscriptions.map(function(subscription) {
|
466
|
-
return _this3.notify.apply(_this3, [ subscription, callbackName ].concat(args));
|
467
|
-
});
|
468
|
-
};
|
469
|
-
Subscriptions.prototype.notify = function notify(subscription, callbackName) {
|
470
|
-
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
|
471
|
-
args[_key2 - 2] = arguments[_key2];
|
472
|
-
}
|
473
|
-
var subscriptions = void 0;
|
406
|
+
}
|
407
|
+
findAll(identifier) {
|
408
|
+
return this.subscriptions.filter((s => s.identifier === identifier));
|
409
|
+
}
|
410
|
+
reload() {
|
411
|
+
return this.subscriptions.map((subscription => this.subscribe(subscription)));
|
412
|
+
}
|
413
|
+
notifyAll(callbackName, ...args) {
|
414
|
+
return this.subscriptions.map((subscription => this.notify(subscription, callbackName, ...args)));
|
415
|
+
}
|
416
|
+
notify(subscription, callbackName, ...args) {
|
417
|
+
let subscriptions;
|
474
418
|
if (typeof subscription === "string") {
|
475
419
|
subscriptions = this.findAll(subscription);
|
476
420
|
} else {
|
477
421
|
subscriptions = [ subscription ];
|
478
422
|
}
|
479
|
-
return subscriptions.map(function(
|
480
|
-
|
481
|
-
|
482
|
-
};
|
483
|
-
Subscriptions.prototype.subscribe = function subscribe(subscription) {
|
423
|
+
return subscriptions.map((subscription => typeof subscription[callbackName] === "function" ? subscription[callbackName](...args) : undefined));
|
424
|
+
}
|
425
|
+
subscribe(subscription) {
|
484
426
|
if (this.sendCommand(subscription, "subscribe")) {
|
485
427
|
this.guarantor.guarantee(subscription);
|
486
428
|
}
|
487
|
-
}
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
}
|
494
|
-
};
|
495
|
-
Subscriptions.prototype.sendCommand = function sendCommand(subscription, command) {
|
496
|
-
var identifier = subscription.identifier;
|
429
|
+
}
|
430
|
+
confirmSubscription(identifier) {
|
431
|
+
logger.log(`Subscription confirmed ${identifier}`);
|
432
|
+
this.findAll(identifier).map((subscription => this.guarantor.forget(subscription)));
|
433
|
+
}
|
434
|
+
sendCommand(subscription, command) {
|
435
|
+
const {identifier: identifier} = subscription;
|
497
436
|
return this.consumer.send({
|
498
437
|
command: command,
|
499
438
|
identifier: identifier
|
500
439
|
});
|
501
|
-
}
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
function Consumer(url) {
|
506
|
-
classCallCheck(this, Consumer);
|
440
|
+
}
|
441
|
+
}
|
442
|
+
class Consumer {
|
443
|
+
constructor(url) {
|
507
444
|
this._url = url;
|
508
445
|
this.subscriptions = new Subscriptions(this);
|
509
446
|
this.connection = new Connection(this);
|
447
|
+
this.subprotocols = [];
|
448
|
+
}
|
449
|
+
get url() {
|
450
|
+
return createWebSocketURL(this._url);
|
510
451
|
}
|
511
|
-
|
452
|
+
send(data) {
|
512
453
|
return this.connection.send(data);
|
513
|
-
}
|
514
|
-
|
454
|
+
}
|
455
|
+
connect() {
|
515
456
|
return this.connection.open();
|
516
|
-
}
|
517
|
-
|
457
|
+
}
|
458
|
+
disconnect() {
|
518
459
|
return this.connection.close({
|
519
460
|
allowReconnect: false
|
520
461
|
});
|
521
|
-
}
|
522
|
-
|
462
|
+
}
|
463
|
+
ensureActiveConnection() {
|
523
464
|
if (!this.connection.isActive()) {
|
524
465
|
return this.connection.open();
|
525
466
|
}
|
526
|
-
}
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
}
|
532
|
-
} ]);
|
533
|
-
return Consumer;
|
534
|
-
}();
|
467
|
+
}
|
468
|
+
addSubProtocol(subprotocol) {
|
469
|
+
this.subprotocols = [ ...this.subprotocols, subprotocol ];
|
470
|
+
}
|
471
|
+
}
|
535
472
|
function createWebSocketURL(url) {
|
536
473
|
if (typeof url === "function") {
|
537
474
|
url = url();
|
538
475
|
}
|
539
476
|
if (url && !/^wss?:/i.test(url)) {
|
540
|
-
|
477
|
+
const a = document.createElement("a");
|
541
478
|
a.href = url;
|
542
479
|
a.href = a.href;
|
543
480
|
a.protocol = a.protocol.replace("http", "ws");
|
@@ -546,29 +483,29 @@
|
|
546
483
|
return url;
|
547
484
|
}
|
548
485
|
}
|
549
|
-
function createConsumer() {
|
550
|
-
var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getConfig("url") || INTERNAL.default_mount_path;
|
486
|
+
function createConsumer(url = getConfig("url") || INTERNAL.default_mount_path) {
|
551
487
|
return new Consumer(url);
|
552
488
|
}
|
553
489
|
function getConfig(name) {
|
554
|
-
|
490
|
+
const element = document.head.querySelector(`meta[name='action-cable-${name}']`);
|
555
491
|
if (element) {
|
556
492
|
return element.getAttribute("content");
|
557
493
|
}
|
558
494
|
}
|
495
|
+
console.log("DEPRECATION: action_cable.js has been renamed to actioncable.js – please update your reference before Rails 8");
|
559
496
|
exports.Connection = Connection;
|
560
497
|
exports.ConnectionMonitor = ConnectionMonitor;
|
561
498
|
exports.Consumer = Consumer;
|
562
499
|
exports.INTERNAL = INTERNAL;
|
563
500
|
exports.Subscription = Subscription;
|
564
|
-
exports.Subscriptions = Subscriptions;
|
565
501
|
exports.SubscriptionGuarantor = SubscriptionGuarantor;
|
502
|
+
exports.Subscriptions = Subscriptions;
|
566
503
|
exports.adapters = adapters;
|
567
|
-
exports.createWebSocketURL = createWebSocketURL;
|
568
|
-
exports.logger = logger;
|
569
504
|
exports.createConsumer = createConsumer;
|
505
|
+
exports.createWebSocketURL = createWebSocketURL;
|
570
506
|
exports.getConfig = getConfig;
|
507
|
+
exports.logger = logger;
|
571
508
|
Object.defineProperty(exports, "__esModule", {
|
572
509
|
value: true
|
573
510
|
});
|
574
|
-
});
|
511
|
+
}));
|