@push-rpc/next 2.0.7 → 2.0.8
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 +2 -0
- package/dist/client/RpcClientImpl.d.ts +1 -1
- package/dist/client/RpcClientImpl.js.map +1 -1
- package/dist/client/WebSocketConnection.d.ts +2 -1
- package/dist/client/WebSocketConnection.js +16 -13
- package/dist/client/WebSocketConnection.js.map +1 -1
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/RpcClientImpl.ts +1 -1
- package/src/client/WebSocketConnection.ts +23 -12
- package/src/client/index.ts +3 -1
- package/tests/subscriptions.ts +62 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ import { ConsumeServicesOptions, RpcClient } from "./index.js";
|
|
|
4
4
|
export declare class RpcClientImpl<S extends Services<S>> implements RpcClient {
|
|
5
5
|
private readonly options;
|
|
6
6
|
constructor(url: string, options: ConsumeServicesOptions);
|
|
7
|
-
|
|
7
|
+
readonly clientId: string;
|
|
8
8
|
private readonly httpClient;
|
|
9
9
|
private readonly remoteSubscriptions;
|
|
10
10
|
private readonly connection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RpcClientImpl.js","sourceRoot":"","sources":["../../src/client/RpcClientImpl.ts"],"names":[],"mappings":";;;AAAA,sCAA2E;AAC3E,mDAA0C;AAC1C,qEAA4D;AAC5D,qEAA4D;AAC5D,mCAA6B;AAC7B,2CAAmE;AAEnE,0DAAsD;AAEtD,MAAa,aAAa;IACxB,YACE,GAAW,EACM,OAA+B;QAA/B,YAAO,GAAP,OAAO,CAAwB;
|
|
1
|
+
{"version":3,"file":"RpcClientImpl.js","sourceRoot":"","sources":["../../src/client/RpcClientImpl.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,9 +13,10 @@ export declare class WebSocketConnection {
|
|
|
13
13
|
}, consume: (itemName: string, parameters: unknown[], data: unknown) => void, onConnected: () => void, onDisconnected: () => void);
|
|
14
14
|
private resolveClose;
|
|
15
15
|
close(): Promise<void>;
|
|
16
|
+
private waitConnectionPromise;
|
|
16
17
|
/**
|
|
17
18
|
* Connect to the server, on each disconnect try to disconnect.
|
|
18
|
-
* Resolves at
|
|
19
|
+
* Resolves at next successful connect. Reconnection loop continues even after resolution
|
|
19
20
|
* Never rejects
|
|
20
21
|
*/
|
|
21
22
|
connect(): Promise<void>;
|
|
@@ -14,7 +14,7 @@ class WebSocketConnection {
|
|
|
14
14
|
this.onDisconnected = onDisconnected;
|
|
15
15
|
this.resolveClose = () => { };
|
|
16
16
|
this.socket = null;
|
|
17
|
-
this.disconnectedMark =
|
|
17
|
+
this.disconnectedMark = false;
|
|
18
18
|
this.pingTimeout = null;
|
|
19
19
|
this.clientId = clientId;
|
|
20
20
|
}
|
|
@@ -29,7 +29,7 @@ class WebSocketConnection {
|
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Connect to the server, on each disconnect try to disconnect.
|
|
32
|
-
* Resolves at
|
|
32
|
+
* Resolves at next successful connect. Reconnection loop continues even after resolution
|
|
33
33
|
* Never rejects
|
|
34
34
|
*/
|
|
35
35
|
connect() {
|
|
@@ -38,24 +38,26 @@ class WebSocketConnection {
|
|
|
38
38
|
return Promise.resolve();
|
|
39
39
|
}
|
|
40
40
|
// already started connecting
|
|
41
|
-
if (this.
|
|
42
|
-
return
|
|
41
|
+
if (this.waitConnectionPromise)
|
|
42
|
+
return this.waitConnectionPromise;
|
|
43
43
|
// start connection process
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
let resolveConnectionPromise;
|
|
45
|
+
let errorDelay = 0;
|
|
46
|
+
this.waitConnectionPromise = new Promise(async (resolve) => {
|
|
47
|
+
resolveConnectionPromise = resolve;
|
|
48
48
|
while (true) {
|
|
49
49
|
// connect, and wait for ...
|
|
50
50
|
await new Promise((resolve) => {
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const connectionPromise = this.establishConnection(() => {
|
|
52
|
+
// 1. ...disconnected
|
|
53
|
+
// recreate promise so new clients will wait for new connection
|
|
54
|
+
this.waitConnectionPromise = new Promise((resolve) => (resolveConnectionPromise = resolve));
|
|
55
|
+
resolve();
|
|
56
|
+
});
|
|
53
57
|
connectionPromise.then(() => {
|
|
54
58
|
// first reconnect after successful connection is done without delay
|
|
55
59
|
errorDelay = 0;
|
|
56
|
-
|
|
57
|
-
onFirstConnection();
|
|
58
|
-
onFirstConnection = () => { };
|
|
60
|
+
resolveConnectionPromise();
|
|
59
61
|
}, (e) => {
|
|
60
62
|
logger_js_1.log.warn("Unable to connect WS", e);
|
|
61
63
|
// 2. ... unable to establish connection
|
|
@@ -74,6 +76,7 @@ class WebSocketConnection {
|
|
|
74
76
|
errorDelay = Math.round(Math.random() * this.options.errorDelayMaxDuration);
|
|
75
77
|
}
|
|
76
78
|
});
|
|
79
|
+
return this.waitConnectionPromise;
|
|
77
80
|
}
|
|
78
81
|
isConnected() {
|
|
79
82
|
return this.socket !== null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketConnection.js","sourceRoot":"","sources":["../../src/client/WebSocketConnection.ts"],"names":[],"mappings":";;;AAAA,4CAAgC;AAChC,8CAA8C;AAC9C,sDAA2C;AAE3C,MAAa,mBAAmB;IAC9B,YACmB,GAAW,EACX,QAAgB,EAChB,OAKhB,EACgB,OAAyE,EACzE,WAAuB,EACvB,cAA0B;QAV1B,QAAG,GAAH,GAAG,CAAQ;QACX,aAAQ,GAAR,QAAQ,CAAQ;QAChB,YAAO,GAAP,OAAO,CAKvB;QACgB,YAAO,GAAP,OAAO,CAAkE;QACzE,gBAAW,GAAX,WAAW,CAAY;QACvB,mBAAc,GAAd,cAAc,CAAY;QAKrC,iBAAY,GAAG,GAAG,EAAE,GAAE,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"WebSocketConnection.js","sourceRoot":"","sources":["../../src/client/WebSocketConnection.ts"],"names":[],"mappings":"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"}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { RpcContext, Services } from "../rpc.js";
|
|
|
2
2
|
import { ServicesWithSubscriptions } from "./remote.js";
|
|
3
3
|
import { Middleware } from "../utils/middleware.js";
|
|
4
4
|
export type RpcClient = {
|
|
5
|
+
readonly clientId: string;
|
|
5
6
|
isConnected(): boolean;
|
|
6
7
|
close(): Promise<void>;
|
|
7
8
|
_allSubscriptions(): Array<any[]>;
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AAEA,yDAAgD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;AAEA,yDAAgD;AA4BzC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,kBAAmD,EAAE;IAKrD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAA;IAC5C,CAAC;IAED,MAAM,OAAO,GAAG;QACd,GAAG,cAAc;QACjB,GAAG,eAAe;KACnB,CAAA;IAED,MAAM,MAAM,GAAG,IAAI,gCAAa,CAAI,GAAG,EAAE,OAAO,CAAC,CAAA;IAEjD,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC5B,MAAM,MAAM,CAAC,OAAO,EAAE,CAAA;IACxB,CAAC;IAED,OAAO;QACL,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE;KAC9B,CAAA;AACH,CAAC;AA1BD,0CA0BC;AAED,MAAM,cAAc,GAA2B;IAC7C,WAAW,EAAE,CAAC,GAAG,IAAI;IACrB,cAAc,EAAE,CAAC;IACjB,qBAAqB,EAAE,EAAE,GAAG,IAAI;IAChC,YAAY,EAAE,IAAI,EAAE,sDAAsD;IAC1E,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,KAAK;IACtB,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC;IACrB,cAAc,EAAE,GAAG,EAAE,GAAE,CAAC;IACxB,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;IAE5B,mBAAmB,CAAC,GAAW;QAC7B,OAAO,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;IACxE,CAAC;CACF,CAAA"}
|
package/package.json
CHANGED
|
@@ -37,7 +37,7 @@ export class RpcClientImpl<S extends Services<S>> implements RpcClient {
|
|
|
37
37
|
)
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
public readonly clientId = nanoid()
|
|
41
41
|
private readonly httpClient: HttpClient
|
|
42
42
|
private readonly remoteSubscriptions: RemoteSubscriptions
|
|
43
43
|
private readonly connection: WebSocketConnection
|
|
@@ -33,9 +33,11 @@ export class WebSocketConnection {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
private waitConnectionPromise: Promise<void> | undefined
|
|
37
|
+
|
|
36
38
|
/**
|
|
37
39
|
* Connect to the server, on each disconnect try to disconnect.
|
|
38
|
-
* Resolves at
|
|
40
|
+
* Resolves at next successful connect. Reconnection loop continues even after resolution
|
|
39
41
|
* Never rejects
|
|
40
42
|
*/
|
|
41
43
|
connect() {
|
|
@@ -45,29 +47,36 @@ export class WebSocketConnection {
|
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
// already started connecting
|
|
48
|
-
if (this.
|
|
50
|
+
if (this.waitConnectionPromise) return this.waitConnectionPromise
|
|
49
51
|
|
|
50
52
|
// start connection process
|
|
51
|
-
this.disconnectedMark = false
|
|
52
53
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
let resolveConnectionPromise: () => void
|
|
55
|
+
let errorDelay = 0
|
|
56
|
+
|
|
57
|
+
this.waitConnectionPromise = new Promise(async (resolve) => {
|
|
58
|
+
resolveConnectionPromise = resolve
|
|
56
59
|
|
|
57
60
|
while (true) {
|
|
58
61
|
// connect, and wait for ...
|
|
59
62
|
await new Promise<void>((resolve) => {
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
const connectionPromise = this.establishConnection(() => {
|
|
64
|
+
// 1. ...disconnected
|
|
65
|
+
|
|
66
|
+
// recreate promise so new clients will wait for new connection
|
|
67
|
+
this.waitConnectionPromise = new Promise(
|
|
68
|
+
(resolve) => (resolveConnectionPromise = resolve)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
resolve()
|
|
72
|
+
})
|
|
62
73
|
|
|
63
74
|
connectionPromise.then(
|
|
64
75
|
() => {
|
|
65
76
|
// first reconnect after successful connection is done without delay
|
|
66
77
|
errorDelay = 0
|
|
67
78
|
|
|
68
|
-
|
|
69
|
-
onFirstConnection()
|
|
70
|
-
onFirstConnection = () => {}
|
|
79
|
+
resolveConnectionPromise()
|
|
71
80
|
},
|
|
72
81
|
(e) => {
|
|
73
82
|
log.warn("Unable to connect WS", e)
|
|
@@ -93,6 +102,8 @@ export class WebSocketConnection {
|
|
|
93
102
|
errorDelay = Math.round(Math.random() * this.options.errorDelayMaxDuration)
|
|
94
103
|
}
|
|
95
104
|
})
|
|
105
|
+
|
|
106
|
+
return this.waitConnectionPromise
|
|
96
107
|
}
|
|
97
108
|
|
|
98
109
|
public isConnected() {
|
|
@@ -162,7 +173,7 @@ export class WebSocketConnection {
|
|
|
162
173
|
}
|
|
163
174
|
|
|
164
175
|
private socket: WebSocket | null = null
|
|
165
|
-
private disconnectedMark =
|
|
176
|
+
private disconnectedMark = false
|
|
166
177
|
private pingTimeout: NodeJS.Timeout | null = null
|
|
167
178
|
|
|
168
179
|
private heartbeat() {
|
package/src/client/index.ts
CHANGED
|
@@ -4,6 +4,8 @@ import {RpcClientImpl} from "./RpcClientImpl.js"
|
|
|
4
4
|
import {Middleware} from "../utils/middleware.js"
|
|
5
5
|
|
|
6
6
|
export type RpcClient = {
|
|
7
|
+
readonly clientId: string
|
|
8
|
+
|
|
7
9
|
isConnected(): boolean
|
|
8
10
|
close(): Promise<void>
|
|
9
11
|
|
|
@@ -65,7 +67,7 @@ const defaultOptions: ConsumeServicesOptions = {
|
|
|
65
67
|
onConnected: () => {},
|
|
66
68
|
onDisconnected: () => {},
|
|
67
69
|
getHeaders: async () => ({}),
|
|
68
|
-
|
|
70
|
+
|
|
69
71
|
getSubscriptionsUrl(url: string): string {
|
|
70
72
|
return url.replace(/^https(.*)/, "wss$1").replace(/^http(.*)/, "ws$1")
|
|
71
73
|
},
|
package/tests/subscriptions.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {assert} from "chai"
|
|
2
2
|
import {createTestClient, startTestServer, testClient, testServer} from "./testUtils.js"
|
|
3
3
|
import {adelay} from "../src/utils/promises.js"
|
|
4
|
-
import {CallOptions, RpcErrors} from "../src/index.js"
|
|
4
|
+
import {CallOptions, RpcConnectionContext, RpcErrors} from "../src/index.js"
|
|
5
|
+
import {IncomingMessage} from "http"
|
|
6
|
+
import {CLIENT_ID_HEADER} from "../src/rpc.js"
|
|
5
7
|
|
|
6
8
|
describe("Subscriptions", () => {
|
|
7
9
|
it("subscribe delivers data", async () => {
|
|
@@ -593,4 +595,63 @@ describe("Subscriptions", () => {
|
|
|
593
595
|
|
|
594
596
|
assert.equal(received, 1)
|
|
595
597
|
})
|
|
598
|
+
|
|
599
|
+
it("subscribe waits for connection", async () => {
|
|
600
|
+
const delay = 50
|
|
601
|
+
|
|
602
|
+
let connectedClients = 0
|
|
603
|
+
let serverCalled = 0
|
|
604
|
+
|
|
605
|
+
const services = await startTestServer(
|
|
606
|
+
{
|
|
607
|
+
test: {
|
|
608
|
+
async op(params: {key: number}): Promise<number> {
|
|
609
|
+
serverCalled++
|
|
610
|
+
return 1
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
async createConnectionContext(req: IncomingMessage): Promise<RpcConnectionContext> {
|
|
616
|
+
const header = req.headers[CLIENT_ID_HEADER]
|
|
617
|
+
|
|
618
|
+
connectedClients++
|
|
619
|
+
|
|
620
|
+
return {
|
|
621
|
+
clientId: (Array.isArray(header) ? header[0] : header) || "anon",
|
|
622
|
+
}
|
|
623
|
+
},
|
|
624
|
+
}
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
const client = await createTestClient<typeof services>({
|
|
628
|
+
callTimeout: 2 * delay,
|
|
629
|
+
})
|
|
630
|
+
|
|
631
|
+
let received1
|
|
632
|
+
let received2
|
|
633
|
+
|
|
634
|
+
client.test.op.subscribe(
|
|
635
|
+
(val) => {
|
|
636
|
+
received1 = val
|
|
637
|
+
},
|
|
638
|
+
{key: 1}
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
await adelay(40)
|
|
642
|
+
|
|
643
|
+
client.test.op.subscribe(
|
|
644
|
+
(val) => {
|
|
645
|
+
received2 = val
|
|
646
|
+
},
|
|
647
|
+
{key: 2}
|
|
648
|
+
)
|
|
649
|
+
|
|
650
|
+
await adelay(1.5 * delay)
|
|
651
|
+
|
|
652
|
+
assert.equal(received1, 1)
|
|
653
|
+
assert.equal(received2, 1)
|
|
654
|
+
assert.equal(serverCalled, 2)
|
|
655
|
+
assert.equal(testServer!._allSubscriptions().length, 2)
|
|
656
|
+
})
|
|
596
657
|
})
|