centrifuge 5.0.1 → 5.1.0
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/README.md +15 -0
- package/build/centrifuge.d.ts +1 -0
- package/build/index.js +36 -36
- package/build/index.mjs +36 -36
- package/build/protobuf/centrifuge.d.ts +1 -0
- package/build/protobuf/index.js +36 -36
- package/build/protobuf/index.mjs +36 -36
- package/dist/centrifuge.js +5 -5
- package/dist/centrifuge.js.map +3 -3
- package/dist/centrifuge.protobuf.js +4 -4
- package/dist/centrifuge.protobuf.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@ The features implemented by this SDK can be found in [SDK feature matrix](https:
|
|
|
27
27
|
* [Protobuf support](#protobuf-support)
|
|
28
28
|
* [Using with NodeJS](#using-with-nodejs)
|
|
29
29
|
* [Custom WebSocket constructor](#custom-websocket-constructor)
|
|
30
|
+
* [Run tests locally](#run-tests-locally)
|
|
30
31
|
|
|
31
32
|
## Install
|
|
32
33
|
|
|
@@ -815,3 +816,17 @@ var centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket', {
|
|
|
815
816
|
```
|
|
816
817
|
|
|
817
818
|
See a basic example with React Native where this technique is used [in this comment](https://github.com/centrifugal/centrifuge-js/issues/224#issuecomment-1538820023).
|
|
819
|
+
|
|
820
|
+
## Run tests locally
|
|
821
|
+
|
|
822
|
+
If you want to run `centrifuge-js` tests locally, start test Centrifugo server:
|
|
823
|
+
|
|
824
|
+
```
|
|
825
|
+
docker compose up
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
Then:
|
|
829
|
+
|
|
830
|
+
```
|
|
831
|
+
yarn test
|
|
832
|
+
```
|
package/build/centrifuge.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ declare const Centrifuge_base: new () => TypedEventEmitter<ClientEvents>;
|
|
|
7
7
|
/** Centrifuge is a Centrifuge/Centrifugo bidirectional client. */
|
|
8
8
|
export declare class Centrifuge extends Centrifuge_base {
|
|
9
9
|
state: State;
|
|
10
|
+
private _transportIsOpen;
|
|
10
11
|
private _endpoint;
|
|
11
12
|
private _emulation;
|
|
12
13
|
private _transports;
|
package/build/index.js
CHANGED
|
@@ -783,12 +783,15 @@ class Subscription extends EventEmitter$1 {
|
|
|
783
783
|
if (this._setState(exports.SubscriptionState.Subscribing)) {
|
|
784
784
|
this.emit('subscribing', { channel: this.channel, code: code, reason: reason });
|
|
785
785
|
}
|
|
786
|
-
this._subscribe(
|
|
786
|
+
this._subscribe();
|
|
787
787
|
}
|
|
788
|
-
_subscribe(
|
|
788
|
+
_subscribe() {
|
|
789
789
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
790
790
|
this._centrifuge._debug('subscribing on', this.channel);
|
|
791
|
-
|
|
791
|
+
// need to check transport readiness here, because there's no point for calling getData or getToken
|
|
792
|
+
// if transport is not ready yet
|
|
793
|
+
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
794
|
+
if (!this._centrifuge._transportIsOpen) {
|
|
792
795
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
793
796
|
this._centrifuge._debug('delay subscribe on', this.channel, 'till connected');
|
|
794
797
|
// subscribe will be called later automatically.
|
|
@@ -805,17 +808,14 @@ class Subscription extends EventEmitter$1 {
|
|
|
805
808
|
return;
|
|
806
809
|
}
|
|
807
810
|
self._data = data;
|
|
808
|
-
self._sendSubscribe(self._token
|
|
811
|
+
self._sendSubscribe(self._token);
|
|
809
812
|
});
|
|
810
813
|
return null;
|
|
811
814
|
}
|
|
812
815
|
else {
|
|
813
|
-
return self._sendSubscribe(self._token
|
|
816
|
+
return self._sendSubscribe(self._token);
|
|
814
817
|
}
|
|
815
818
|
}
|
|
816
|
-
if (optimistic) {
|
|
817
|
-
return null;
|
|
818
|
-
}
|
|
819
819
|
this._getSubscriptionToken().then(function (token) {
|
|
820
820
|
if (!self._isSubscribing()) {
|
|
821
821
|
return;
|
|
@@ -831,11 +831,11 @@ class Subscription extends EventEmitter$1 {
|
|
|
831
831
|
return;
|
|
832
832
|
}
|
|
833
833
|
self._data = data;
|
|
834
|
-
self._sendSubscribe(token
|
|
834
|
+
self._sendSubscribe(token);
|
|
835
835
|
});
|
|
836
836
|
}
|
|
837
837
|
else {
|
|
838
|
-
self._sendSubscribe(token
|
|
838
|
+
self._sendSubscribe(token);
|
|
839
839
|
}
|
|
840
840
|
}).catch(function (e) {
|
|
841
841
|
if (!self._isSubscribing()) {
|
|
@@ -857,7 +857,13 @@ class Subscription extends EventEmitter$1 {
|
|
|
857
857
|
});
|
|
858
858
|
return null;
|
|
859
859
|
}
|
|
860
|
-
_sendSubscribe(token
|
|
860
|
+
_sendSubscribe(token) {
|
|
861
|
+
// we also need to check for transport state before sending subscription
|
|
862
|
+
// because it may change for subscription with side effects (getData, getToken options)
|
|
863
|
+
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
864
|
+
if (!this._centrifuge._transportIsOpen) {
|
|
865
|
+
return null;
|
|
866
|
+
}
|
|
861
867
|
const channel = this.channel;
|
|
862
868
|
const req = {
|
|
863
869
|
channel: channel
|
|
@@ -891,7 +897,7 @@ class Subscription extends EventEmitter$1 {
|
|
|
891
897
|
const cmd = { subscribe: req };
|
|
892
898
|
this._inflight = true;
|
|
893
899
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
894
|
-
this._centrifuge._call(cmd
|
|
900
|
+
this._centrifuge._call(cmd).then(resolveCtx => {
|
|
895
901
|
this._inflight = false;
|
|
896
902
|
// @ts-ignore - improve later.
|
|
897
903
|
const result = resolveCtx.reply.subscribe;
|
|
@@ -997,7 +1003,7 @@ class Subscription extends EventEmitter$1 {
|
|
|
997
1003
|
const delay = this._getResubscribeDelay();
|
|
998
1004
|
this._resubscribeTimeout = setTimeout(function () {
|
|
999
1005
|
if (self._isSubscribing()) {
|
|
1000
|
-
self._subscribe(
|
|
1006
|
+
self._subscribe();
|
|
1001
1007
|
}
|
|
1002
1008
|
}, delay);
|
|
1003
1009
|
}
|
|
@@ -1820,6 +1826,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
1820
1826
|
this._refreshTimeout = null;
|
|
1821
1827
|
this._serverPingTimeout = null;
|
|
1822
1828
|
this.state = exports.State.Disconnected;
|
|
1829
|
+
this._transportIsOpen = false;
|
|
1823
1830
|
this._endpoint = endpoint;
|
|
1824
1831
|
this._emulation = false;
|
|
1825
1832
|
this._transports = [];
|
|
@@ -2425,25 +2432,10 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2425
2432
|
const transportId = this._nextTransportId();
|
|
2426
2433
|
self._debug("id of transport", transportId);
|
|
2427
2434
|
let wasOpen = false;
|
|
2428
|
-
let optimistic = true;
|
|
2429
|
-
if (this._transport.name() === 'sse') {
|
|
2430
|
-
// Avoid using optimistic subscriptions with SSE/EventSource as we are sending
|
|
2431
|
-
// initial data in URL params. URL is recommended to be 2048 chars max – so adding
|
|
2432
|
-
// subscription data may be risky.
|
|
2433
|
-
optimistic = false;
|
|
2434
|
-
}
|
|
2435
2435
|
const initialCommands = [];
|
|
2436
2436
|
if (this._transport.emulation()) {
|
|
2437
2437
|
const connectCommand = self._sendConnect(true);
|
|
2438
2438
|
initialCommands.push(connectCommand);
|
|
2439
|
-
if (optimistic) {
|
|
2440
|
-
const subscribeCommands = self._sendSubscribeCommands(true, true);
|
|
2441
|
-
for (const i in subscribeCommands) {
|
|
2442
|
-
if (subscribeCommands.hasOwnProperty(i)) {
|
|
2443
|
-
initialCommands.push(subscribeCommands[i]);
|
|
2444
|
-
}
|
|
2445
|
-
}
|
|
2446
|
-
}
|
|
2447
2439
|
}
|
|
2448
2440
|
this._setNetworkEvents();
|
|
2449
2441
|
const initialData = this._codec.encodeCommands(initialCommands);
|
|
@@ -2465,16 +2457,17 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2465
2457
|
}
|
|
2466
2458
|
wasOpen = true;
|
|
2467
2459
|
self._debug(transport.subName(), 'transport open');
|
|
2468
|
-
self._transportWasOpen = true;
|
|
2469
2460
|
if (transport.emulation()) {
|
|
2470
2461
|
return;
|
|
2471
2462
|
}
|
|
2463
|
+
self._transportIsOpen = true;
|
|
2464
|
+
self._transportWasOpen = true;
|
|
2472
2465
|
self.startBatching();
|
|
2473
2466
|
self._sendConnect(false);
|
|
2474
|
-
|
|
2475
|
-
self._sendSubscribeCommands(true, false);
|
|
2476
|
-
}
|
|
2467
|
+
self._sendSubscribeCommands();
|
|
2477
2468
|
self.stopBatching();
|
|
2469
|
+
//@ts-ignore must be used only for debug and test purposes. Exposed only for non-emulation transport.
|
|
2470
|
+
self.emit('__centrifuge_debug:connect_frame_sent', {});
|
|
2478
2471
|
},
|
|
2479
2472
|
onError: function (e) {
|
|
2480
2473
|
if (self._transportId != transportId) {
|
|
@@ -2494,6 +2487,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2494
2487
|
}
|
|
2495
2488
|
self._debug(transport.subName(), 'transport closed');
|
|
2496
2489
|
self._transportClosed = true;
|
|
2490
|
+
self._transportIsOpen = false;
|
|
2497
2491
|
let reason = 'connection closed';
|
|
2498
2492
|
let needReconnect = true;
|
|
2499
2493
|
let code = 0;
|
|
@@ -2857,6 +2851,9 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2857
2851
|
if (this._isDisconnected()) {
|
|
2858
2852
|
return;
|
|
2859
2853
|
}
|
|
2854
|
+
// we mark transport is closed right away, because _clearConnectedState will move subscriptions to subscribing state
|
|
2855
|
+
// if transport will still be open at this time, subscribe frames will be sent to closing transport
|
|
2856
|
+
this._transportIsOpen = false;
|
|
2860
2857
|
const previousState = this.state;
|
|
2861
2858
|
const ctx = {
|
|
2862
2859
|
code: code,
|
|
@@ -2890,6 +2887,8 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2890
2887
|
const transport = this._transport;
|
|
2891
2888
|
this._transport = null;
|
|
2892
2889
|
transport.close(); // Close only after setting this._transport to null to avoid recursion when calling transport close().
|
|
2890
|
+
// Need to mark as closed here, because connect call may be sync called after disconnect,
|
|
2891
|
+
// transport onClose callback will not be called yet
|
|
2893
2892
|
this._transportClosed = true;
|
|
2894
2893
|
this._nextTransportId();
|
|
2895
2894
|
}
|
|
@@ -2999,7 +2998,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2999
2998
|
delete this._subs[sub.channel];
|
|
3000
2999
|
}
|
|
3001
3000
|
_unsubscribe(sub) {
|
|
3002
|
-
if (!this.
|
|
3001
|
+
if (!this._transportIsOpen) {
|
|
3003
3002
|
return;
|
|
3004
3003
|
}
|
|
3005
3004
|
const req = {
|
|
@@ -3030,7 +3029,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
3030
3029
|
_isServerSub(channel) {
|
|
3031
3030
|
return this._serverSubs[channel] !== undefined;
|
|
3032
3031
|
}
|
|
3033
|
-
_sendSubscribeCommands(
|
|
3032
|
+
_sendSubscribeCommands() {
|
|
3034
3033
|
const commands = [];
|
|
3035
3034
|
for (const channel in this._subs) {
|
|
3036
3035
|
if (!this._subs.hasOwnProperty(channel)) {
|
|
@@ -3043,7 +3042,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
3043
3042
|
}
|
|
3044
3043
|
if (sub.state === exports.SubscriptionState.Subscribing) {
|
|
3045
3044
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
3046
|
-
const cmd = sub._subscribe(
|
|
3045
|
+
const cmd = sub._subscribe();
|
|
3047
3046
|
if (cmd) {
|
|
3048
3047
|
commands.push(cmd);
|
|
3049
3048
|
}
|
|
@@ -3052,6 +3051,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
3052
3051
|
return commands;
|
|
3053
3052
|
}
|
|
3054
3053
|
_connectResponse(result) {
|
|
3054
|
+
this._transportIsOpen = true;
|
|
3055
3055
|
this._transportWasOpen = true;
|
|
3056
3056
|
this._reconnectAttempts = 0;
|
|
3057
3057
|
this._refreshRequired = false;
|
|
@@ -3069,7 +3069,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
3069
3069
|
this._session = result.session;
|
|
3070
3070
|
this._node = result.node;
|
|
3071
3071
|
this.startBatching();
|
|
3072
|
-
this._sendSubscribeCommands(
|
|
3072
|
+
this._sendSubscribeCommands();
|
|
3073
3073
|
this.stopBatching();
|
|
3074
3074
|
const ctx = {
|
|
3075
3075
|
client: result.client,
|
package/build/index.mjs
CHANGED
|
@@ -781,12 +781,15 @@ class Subscription extends EventEmitter$1 {
|
|
|
781
781
|
if (this._setState(SubscriptionState.Subscribing)) {
|
|
782
782
|
this.emit('subscribing', { channel: this.channel, code: code, reason: reason });
|
|
783
783
|
}
|
|
784
|
-
this._subscribe(
|
|
784
|
+
this._subscribe();
|
|
785
785
|
}
|
|
786
|
-
_subscribe(
|
|
786
|
+
_subscribe() {
|
|
787
787
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
788
788
|
this._centrifuge._debug('subscribing on', this.channel);
|
|
789
|
-
|
|
789
|
+
// need to check transport readiness here, because there's no point for calling getData or getToken
|
|
790
|
+
// if transport is not ready yet
|
|
791
|
+
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
792
|
+
if (!this._centrifuge._transportIsOpen) {
|
|
790
793
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
791
794
|
this._centrifuge._debug('delay subscribe on', this.channel, 'till connected');
|
|
792
795
|
// subscribe will be called later automatically.
|
|
@@ -803,17 +806,14 @@ class Subscription extends EventEmitter$1 {
|
|
|
803
806
|
return;
|
|
804
807
|
}
|
|
805
808
|
self._data = data;
|
|
806
|
-
self._sendSubscribe(self._token
|
|
809
|
+
self._sendSubscribe(self._token);
|
|
807
810
|
});
|
|
808
811
|
return null;
|
|
809
812
|
}
|
|
810
813
|
else {
|
|
811
|
-
return self._sendSubscribe(self._token
|
|
814
|
+
return self._sendSubscribe(self._token);
|
|
812
815
|
}
|
|
813
816
|
}
|
|
814
|
-
if (optimistic) {
|
|
815
|
-
return null;
|
|
816
|
-
}
|
|
817
817
|
this._getSubscriptionToken().then(function (token) {
|
|
818
818
|
if (!self._isSubscribing()) {
|
|
819
819
|
return;
|
|
@@ -829,11 +829,11 @@ class Subscription extends EventEmitter$1 {
|
|
|
829
829
|
return;
|
|
830
830
|
}
|
|
831
831
|
self._data = data;
|
|
832
|
-
self._sendSubscribe(token
|
|
832
|
+
self._sendSubscribe(token);
|
|
833
833
|
});
|
|
834
834
|
}
|
|
835
835
|
else {
|
|
836
|
-
self._sendSubscribe(token
|
|
836
|
+
self._sendSubscribe(token);
|
|
837
837
|
}
|
|
838
838
|
}).catch(function (e) {
|
|
839
839
|
if (!self._isSubscribing()) {
|
|
@@ -855,7 +855,13 @@ class Subscription extends EventEmitter$1 {
|
|
|
855
855
|
});
|
|
856
856
|
return null;
|
|
857
857
|
}
|
|
858
|
-
_sendSubscribe(token
|
|
858
|
+
_sendSubscribe(token) {
|
|
859
|
+
// we also need to check for transport state before sending subscription
|
|
860
|
+
// because it may change for subscription with side effects (getData, getToken options)
|
|
861
|
+
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
862
|
+
if (!this._centrifuge._transportIsOpen) {
|
|
863
|
+
return null;
|
|
864
|
+
}
|
|
859
865
|
const channel = this.channel;
|
|
860
866
|
const req = {
|
|
861
867
|
channel: channel
|
|
@@ -889,7 +895,7 @@ class Subscription extends EventEmitter$1 {
|
|
|
889
895
|
const cmd = { subscribe: req };
|
|
890
896
|
this._inflight = true;
|
|
891
897
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
892
|
-
this._centrifuge._call(cmd
|
|
898
|
+
this._centrifuge._call(cmd).then(resolveCtx => {
|
|
893
899
|
this._inflight = false;
|
|
894
900
|
// @ts-ignore - improve later.
|
|
895
901
|
const result = resolveCtx.reply.subscribe;
|
|
@@ -995,7 +1001,7 @@ class Subscription extends EventEmitter$1 {
|
|
|
995
1001
|
const delay = this._getResubscribeDelay();
|
|
996
1002
|
this._resubscribeTimeout = setTimeout(function () {
|
|
997
1003
|
if (self._isSubscribing()) {
|
|
998
|
-
self._subscribe(
|
|
1004
|
+
self._subscribe();
|
|
999
1005
|
}
|
|
1000
1006
|
}, delay);
|
|
1001
1007
|
}
|
|
@@ -1818,6 +1824,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
1818
1824
|
this._refreshTimeout = null;
|
|
1819
1825
|
this._serverPingTimeout = null;
|
|
1820
1826
|
this.state = State.Disconnected;
|
|
1827
|
+
this._transportIsOpen = false;
|
|
1821
1828
|
this._endpoint = endpoint;
|
|
1822
1829
|
this._emulation = false;
|
|
1823
1830
|
this._transports = [];
|
|
@@ -2423,25 +2430,10 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2423
2430
|
const transportId = this._nextTransportId();
|
|
2424
2431
|
self._debug("id of transport", transportId);
|
|
2425
2432
|
let wasOpen = false;
|
|
2426
|
-
let optimistic = true;
|
|
2427
|
-
if (this._transport.name() === 'sse') {
|
|
2428
|
-
// Avoid using optimistic subscriptions with SSE/EventSource as we are sending
|
|
2429
|
-
// initial data in URL params. URL is recommended to be 2048 chars max – so adding
|
|
2430
|
-
// subscription data may be risky.
|
|
2431
|
-
optimistic = false;
|
|
2432
|
-
}
|
|
2433
2433
|
const initialCommands = [];
|
|
2434
2434
|
if (this._transport.emulation()) {
|
|
2435
2435
|
const connectCommand = self._sendConnect(true);
|
|
2436
2436
|
initialCommands.push(connectCommand);
|
|
2437
|
-
if (optimistic) {
|
|
2438
|
-
const subscribeCommands = self._sendSubscribeCommands(true, true);
|
|
2439
|
-
for (const i in subscribeCommands) {
|
|
2440
|
-
if (subscribeCommands.hasOwnProperty(i)) {
|
|
2441
|
-
initialCommands.push(subscribeCommands[i]);
|
|
2442
|
-
}
|
|
2443
|
-
}
|
|
2444
|
-
}
|
|
2445
2437
|
}
|
|
2446
2438
|
this._setNetworkEvents();
|
|
2447
2439
|
const initialData = this._codec.encodeCommands(initialCommands);
|
|
@@ -2463,16 +2455,17 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2463
2455
|
}
|
|
2464
2456
|
wasOpen = true;
|
|
2465
2457
|
self._debug(transport.subName(), 'transport open');
|
|
2466
|
-
self._transportWasOpen = true;
|
|
2467
2458
|
if (transport.emulation()) {
|
|
2468
2459
|
return;
|
|
2469
2460
|
}
|
|
2461
|
+
self._transportIsOpen = true;
|
|
2462
|
+
self._transportWasOpen = true;
|
|
2470
2463
|
self.startBatching();
|
|
2471
2464
|
self._sendConnect(false);
|
|
2472
|
-
|
|
2473
|
-
self._sendSubscribeCommands(true, false);
|
|
2474
|
-
}
|
|
2465
|
+
self._sendSubscribeCommands();
|
|
2475
2466
|
self.stopBatching();
|
|
2467
|
+
//@ts-ignore must be used only for debug and test purposes. Exposed only for non-emulation transport.
|
|
2468
|
+
self.emit('__centrifuge_debug:connect_frame_sent', {});
|
|
2476
2469
|
},
|
|
2477
2470
|
onError: function (e) {
|
|
2478
2471
|
if (self._transportId != transportId) {
|
|
@@ -2492,6 +2485,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2492
2485
|
}
|
|
2493
2486
|
self._debug(transport.subName(), 'transport closed');
|
|
2494
2487
|
self._transportClosed = true;
|
|
2488
|
+
self._transportIsOpen = false;
|
|
2495
2489
|
let reason = 'connection closed';
|
|
2496
2490
|
let needReconnect = true;
|
|
2497
2491
|
let code = 0;
|
|
@@ -2855,6 +2849,9 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2855
2849
|
if (this._isDisconnected()) {
|
|
2856
2850
|
return;
|
|
2857
2851
|
}
|
|
2852
|
+
// we mark transport is closed right away, because _clearConnectedState will move subscriptions to subscribing state
|
|
2853
|
+
// if transport will still be open at this time, subscribe frames will be sent to closing transport
|
|
2854
|
+
this._transportIsOpen = false;
|
|
2858
2855
|
const previousState = this.state;
|
|
2859
2856
|
const ctx = {
|
|
2860
2857
|
code: code,
|
|
@@ -2888,6 +2885,8 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2888
2885
|
const transport = this._transport;
|
|
2889
2886
|
this._transport = null;
|
|
2890
2887
|
transport.close(); // Close only after setting this._transport to null to avoid recursion when calling transport close().
|
|
2888
|
+
// Need to mark as closed here, because connect call may be sync called after disconnect,
|
|
2889
|
+
// transport onClose callback will not be called yet
|
|
2891
2890
|
this._transportClosed = true;
|
|
2892
2891
|
this._nextTransportId();
|
|
2893
2892
|
}
|
|
@@ -2997,7 +2996,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
2997
2996
|
delete this._subs[sub.channel];
|
|
2998
2997
|
}
|
|
2999
2998
|
_unsubscribe(sub) {
|
|
3000
|
-
if (!this.
|
|
2999
|
+
if (!this._transportIsOpen) {
|
|
3001
3000
|
return;
|
|
3002
3001
|
}
|
|
3003
3002
|
const req = {
|
|
@@ -3028,7 +3027,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
3028
3027
|
_isServerSub(channel) {
|
|
3029
3028
|
return this._serverSubs[channel] !== undefined;
|
|
3030
3029
|
}
|
|
3031
|
-
_sendSubscribeCommands(
|
|
3030
|
+
_sendSubscribeCommands() {
|
|
3032
3031
|
const commands = [];
|
|
3033
3032
|
for (const channel in this._subs) {
|
|
3034
3033
|
if (!this._subs.hasOwnProperty(channel)) {
|
|
@@ -3041,7 +3040,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
3041
3040
|
}
|
|
3042
3041
|
if (sub.state === SubscriptionState.Subscribing) {
|
|
3043
3042
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
3044
|
-
const cmd = sub._subscribe(
|
|
3043
|
+
const cmd = sub._subscribe();
|
|
3045
3044
|
if (cmd) {
|
|
3046
3045
|
commands.push(cmd);
|
|
3047
3046
|
}
|
|
@@ -3050,6 +3049,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
3050
3049
|
return commands;
|
|
3051
3050
|
}
|
|
3052
3051
|
_connectResponse(result) {
|
|
3052
|
+
this._transportIsOpen = true;
|
|
3053
3053
|
this._transportWasOpen = true;
|
|
3054
3054
|
this._reconnectAttempts = 0;
|
|
3055
3055
|
this._refreshRequired = false;
|
|
@@ -3067,7 +3067,7 @@ class Centrifuge extends EventEmitter$1 {
|
|
|
3067
3067
|
this._session = result.session;
|
|
3068
3068
|
this._node = result.node;
|
|
3069
3069
|
this.startBatching();
|
|
3070
|
-
this._sendSubscribeCommands(
|
|
3070
|
+
this._sendSubscribeCommands();
|
|
3071
3071
|
this.stopBatching();
|
|
3072
3072
|
const ctx = {
|
|
3073
3073
|
client: result.client,
|
|
@@ -7,6 +7,7 @@ declare const Centrifuge_base: new () => TypedEventEmitter<ClientEvents>;
|
|
|
7
7
|
/** Centrifuge is a Centrifuge/Centrifugo bidirectional client. */
|
|
8
8
|
export declare class Centrifuge extends Centrifuge_base {
|
|
9
9
|
state: State;
|
|
10
|
+
private _transportIsOpen;
|
|
10
11
|
private _endpoint;
|
|
11
12
|
private _emulation;
|
|
12
13
|
private _transports;
|
package/build/protobuf/index.js
CHANGED
|
@@ -785,12 +785,15 @@ class Subscription extends EventEmitter$2 {
|
|
|
785
785
|
if (this._setState(exports.SubscriptionState.Subscribing)) {
|
|
786
786
|
this.emit('subscribing', { channel: this.channel, code: code, reason: reason });
|
|
787
787
|
}
|
|
788
|
-
this._subscribe(
|
|
788
|
+
this._subscribe();
|
|
789
789
|
}
|
|
790
|
-
_subscribe(
|
|
790
|
+
_subscribe() {
|
|
791
791
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
792
792
|
this._centrifuge._debug('subscribing on', this.channel);
|
|
793
|
-
|
|
793
|
+
// need to check transport readiness here, because there's no point for calling getData or getToken
|
|
794
|
+
// if transport is not ready yet
|
|
795
|
+
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
796
|
+
if (!this._centrifuge._transportIsOpen) {
|
|
794
797
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
795
798
|
this._centrifuge._debug('delay subscribe on', this.channel, 'till connected');
|
|
796
799
|
// subscribe will be called later automatically.
|
|
@@ -807,17 +810,14 @@ class Subscription extends EventEmitter$2 {
|
|
|
807
810
|
return;
|
|
808
811
|
}
|
|
809
812
|
self._data = data;
|
|
810
|
-
self._sendSubscribe(self._token
|
|
813
|
+
self._sendSubscribe(self._token);
|
|
811
814
|
});
|
|
812
815
|
return null;
|
|
813
816
|
}
|
|
814
817
|
else {
|
|
815
|
-
return self._sendSubscribe(self._token
|
|
818
|
+
return self._sendSubscribe(self._token);
|
|
816
819
|
}
|
|
817
820
|
}
|
|
818
|
-
if (optimistic) {
|
|
819
|
-
return null;
|
|
820
|
-
}
|
|
821
821
|
this._getSubscriptionToken().then(function (token) {
|
|
822
822
|
if (!self._isSubscribing()) {
|
|
823
823
|
return;
|
|
@@ -833,11 +833,11 @@ class Subscription extends EventEmitter$2 {
|
|
|
833
833
|
return;
|
|
834
834
|
}
|
|
835
835
|
self._data = data;
|
|
836
|
-
self._sendSubscribe(token
|
|
836
|
+
self._sendSubscribe(token);
|
|
837
837
|
});
|
|
838
838
|
}
|
|
839
839
|
else {
|
|
840
|
-
self._sendSubscribe(token
|
|
840
|
+
self._sendSubscribe(token);
|
|
841
841
|
}
|
|
842
842
|
}).catch(function (e) {
|
|
843
843
|
if (!self._isSubscribing()) {
|
|
@@ -859,7 +859,13 @@ class Subscription extends EventEmitter$2 {
|
|
|
859
859
|
});
|
|
860
860
|
return null;
|
|
861
861
|
}
|
|
862
|
-
_sendSubscribe(token
|
|
862
|
+
_sendSubscribe(token) {
|
|
863
|
+
// we also need to check for transport state before sending subscription
|
|
864
|
+
// because it may change for subscription with side effects (getData, getToken options)
|
|
865
|
+
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
866
|
+
if (!this._centrifuge._transportIsOpen) {
|
|
867
|
+
return null;
|
|
868
|
+
}
|
|
863
869
|
const channel = this.channel;
|
|
864
870
|
const req = {
|
|
865
871
|
channel: channel
|
|
@@ -893,7 +899,7 @@ class Subscription extends EventEmitter$2 {
|
|
|
893
899
|
const cmd = { subscribe: req };
|
|
894
900
|
this._inflight = true;
|
|
895
901
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
896
|
-
this._centrifuge._call(cmd
|
|
902
|
+
this._centrifuge._call(cmd).then(resolveCtx => {
|
|
897
903
|
this._inflight = false;
|
|
898
904
|
// @ts-ignore - improve later.
|
|
899
905
|
const result = resolveCtx.reply.subscribe;
|
|
@@ -999,7 +1005,7 @@ class Subscription extends EventEmitter$2 {
|
|
|
999
1005
|
const delay = this._getResubscribeDelay();
|
|
1000
1006
|
this._resubscribeTimeout = setTimeout(function () {
|
|
1001
1007
|
if (self._isSubscribing()) {
|
|
1002
|
-
self._subscribe(
|
|
1008
|
+
self._subscribe();
|
|
1003
1009
|
}
|
|
1004
1010
|
}, delay);
|
|
1005
1011
|
}
|
|
@@ -1822,6 +1828,7 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
1822
1828
|
this._refreshTimeout = null;
|
|
1823
1829
|
this._serverPingTimeout = null;
|
|
1824
1830
|
this.state = exports.State.Disconnected;
|
|
1831
|
+
this._transportIsOpen = false;
|
|
1825
1832
|
this._endpoint = endpoint;
|
|
1826
1833
|
this._emulation = false;
|
|
1827
1834
|
this._transports = [];
|
|
@@ -2427,25 +2434,10 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
2427
2434
|
const transportId = this._nextTransportId();
|
|
2428
2435
|
self._debug("id of transport", transportId);
|
|
2429
2436
|
let wasOpen = false;
|
|
2430
|
-
let optimistic = true;
|
|
2431
|
-
if (this._transport.name() === 'sse') {
|
|
2432
|
-
// Avoid using optimistic subscriptions with SSE/EventSource as we are sending
|
|
2433
|
-
// initial data in URL params. URL is recommended to be 2048 chars max – so adding
|
|
2434
|
-
// subscription data may be risky.
|
|
2435
|
-
optimistic = false;
|
|
2436
|
-
}
|
|
2437
2437
|
const initialCommands = [];
|
|
2438
2438
|
if (this._transport.emulation()) {
|
|
2439
2439
|
const connectCommand = self._sendConnect(true);
|
|
2440
2440
|
initialCommands.push(connectCommand);
|
|
2441
|
-
if (optimistic) {
|
|
2442
|
-
const subscribeCommands = self._sendSubscribeCommands(true, true);
|
|
2443
|
-
for (const i in subscribeCommands) {
|
|
2444
|
-
if (subscribeCommands.hasOwnProperty(i)) {
|
|
2445
|
-
initialCommands.push(subscribeCommands[i]);
|
|
2446
|
-
}
|
|
2447
|
-
}
|
|
2448
|
-
}
|
|
2449
2441
|
}
|
|
2450
2442
|
this._setNetworkEvents();
|
|
2451
2443
|
const initialData = this._codec.encodeCommands(initialCommands);
|
|
@@ -2467,16 +2459,17 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
2467
2459
|
}
|
|
2468
2460
|
wasOpen = true;
|
|
2469
2461
|
self._debug(transport.subName(), 'transport open');
|
|
2470
|
-
self._transportWasOpen = true;
|
|
2471
2462
|
if (transport.emulation()) {
|
|
2472
2463
|
return;
|
|
2473
2464
|
}
|
|
2465
|
+
self._transportIsOpen = true;
|
|
2466
|
+
self._transportWasOpen = true;
|
|
2474
2467
|
self.startBatching();
|
|
2475
2468
|
self._sendConnect(false);
|
|
2476
|
-
|
|
2477
|
-
self._sendSubscribeCommands(true, false);
|
|
2478
|
-
}
|
|
2469
|
+
self._sendSubscribeCommands();
|
|
2479
2470
|
self.stopBatching();
|
|
2471
|
+
//@ts-ignore must be used only for debug and test purposes. Exposed only for non-emulation transport.
|
|
2472
|
+
self.emit('__centrifuge_debug:connect_frame_sent', {});
|
|
2480
2473
|
},
|
|
2481
2474
|
onError: function (e) {
|
|
2482
2475
|
if (self._transportId != transportId) {
|
|
@@ -2496,6 +2489,7 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
2496
2489
|
}
|
|
2497
2490
|
self._debug(transport.subName(), 'transport closed');
|
|
2498
2491
|
self._transportClosed = true;
|
|
2492
|
+
self._transportIsOpen = false;
|
|
2499
2493
|
let reason = 'connection closed';
|
|
2500
2494
|
let needReconnect = true;
|
|
2501
2495
|
let code = 0;
|
|
@@ -2859,6 +2853,9 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
2859
2853
|
if (this._isDisconnected()) {
|
|
2860
2854
|
return;
|
|
2861
2855
|
}
|
|
2856
|
+
// we mark transport is closed right away, because _clearConnectedState will move subscriptions to subscribing state
|
|
2857
|
+
// if transport will still be open at this time, subscribe frames will be sent to closing transport
|
|
2858
|
+
this._transportIsOpen = false;
|
|
2862
2859
|
const previousState = this.state;
|
|
2863
2860
|
const ctx = {
|
|
2864
2861
|
code: code,
|
|
@@ -2892,6 +2889,8 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
2892
2889
|
const transport = this._transport;
|
|
2893
2890
|
this._transport = null;
|
|
2894
2891
|
transport.close(); // Close only after setting this._transport to null to avoid recursion when calling transport close().
|
|
2892
|
+
// Need to mark as closed here, because connect call may be sync called after disconnect,
|
|
2893
|
+
// transport onClose callback will not be called yet
|
|
2895
2894
|
this._transportClosed = true;
|
|
2896
2895
|
this._nextTransportId();
|
|
2897
2896
|
}
|
|
@@ -3001,7 +3000,7 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
3001
3000
|
delete this._subs[sub.channel];
|
|
3002
3001
|
}
|
|
3003
3002
|
_unsubscribe(sub) {
|
|
3004
|
-
if (!this.
|
|
3003
|
+
if (!this._transportIsOpen) {
|
|
3005
3004
|
return;
|
|
3006
3005
|
}
|
|
3007
3006
|
const req = {
|
|
@@ -3032,7 +3031,7 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
3032
3031
|
_isServerSub(channel) {
|
|
3033
3032
|
return this._serverSubs[channel] !== undefined;
|
|
3034
3033
|
}
|
|
3035
|
-
_sendSubscribeCommands(
|
|
3034
|
+
_sendSubscribeCommands() {
|
|
3036
3035
|
const commands = [];
|
|
3037
3036
|
for (const channel in this._subs) {
|
|
3038
3037
|
if (!this._subs.hasOwnProperty(channel)) {
|
|
@@ -3045,7 +3044,7 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
3045
3044
|
}
|
|
3046
3045
|
if (sub.state === exports.SubscriptionState.Subscribing) {
|
|
3047
3046
|
// @ts-ignore – we are hiding some symbols from public API autocompletion.
|
|
3048
|
-
const cmd = sub._subscribe(
|
|
3047
|
+
const cmd = sub._subscribe();
|
|
3049
3048
|
if (cmd) {
|
|
3050
3049
|
commands.push(cmd);
|
|
3051
3050
|
}
|
|
@@ -3054,6 +3053,7 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
3054
3053
|
return commands;
|
|
3055
3054
|
}
|
|
3056
3055
|
_connectResponse(result) {
|
|
3056
|
+
this._transportIsOpen = true;
|
|
3057
3057
|
this._transportWasOpen = true;
|
|
3058
3058
|
this._reconnectAttempts = 0;
|
|
3059
3059
|
this._refreshRequired = false;
|
|
@@ -3071,7 +3071,7 @@ class Centrifuge extends EventEmitter$2 {
|
|
|
3071
3071
|
this._session = result.session;
|
|
3072
3072
|
this._node = result.node;
|
|
3073
3073
|
this.startBatching();
|
|
3074
|
-
this._sendSubscribeCommands(
|
|
3074
|
+
this._sendSubscribeCommands();
|
|
3075
3075
|
this.stopBatching();
|
|
3076
3076
|
const ctx = {
|
|
3077
3077
|
client: result.client,
|