@push-rpc/next 2.0.19 → 2.0.20
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 +4 -3
- package/dist/client/RpcClientImpl.js +11 -10
- package/dist/client/RpcClientImpl.js.map +1 -1
- package/dist/server/RpcServerImpl.d.ts +0 -1
- package/dist/server/RpcServerImpl.js +8 -12
- package/dist/server/RpcServerImpl.js.map +1 -1
- package/dist/utils/promises.d.ts +0 -4
- package/dist/utils/promises.js +1 -22
- package/dist/utils/promises.js.map +1 -1
- package/package.json +1 -1
- package/src/client/RpcClientImpl.ts +13 -11
- package/src/server/ConnectionsServer.ts +1 -1
- package/src/server/RpcServerImpl.ts +21 -27
- package/src/utils/promises.ts +0 -22
- package/tests/calls.ts +1 -36
- package/tests/middleware.ts +8 -3
- package/tests/subscriptions.ts +69 -97
- package/tests/triggers.ts +6 -2
package/README.md
CHANGED
|
@@ -170,8 +170,9 @@ There are the types of messages that can be sent from client to server:
|
|
|
170
170
|
[{"id": 1, text: "Buy groceries", status: "open"}]
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
173
|
+
Server accepts subscribe requests before WS connection is established. Server do not track client subscriptions.
|
|
174
|
+
On WS connection established, client should re-sent subscribe requests. In response, server will provide up-to-date
|
|
175
|
+
data.
|
|
175
176
|
|
|
176
177
|
3. **Unsubscribe** - a request to unsubscribe from a remote function updates. Implemented as HTTP PATCH request. URL
|
|
177
178
|
contains the remote function name. Body contains JSON-encoded list of arguments. Response is always empty.
|
|
@@ -205,7 +206,7 @@ topic name, remote function result and subscription parameters if any:
|
|
|
205
206
|
["todo/getTodos", [{"id": 1, text: "Buy groceries", status: "open"}], ...]
|
|
206
207
|
```
|
|
207
208
|
|
|
208
|
-
Both client & server will try to
|
|
209
|
+
Both client & server will try to detect broken connections by sending WS ping/pongs.
|
|
209
210
|
|
|
210
211
|
## Glossary
|
|
211
212
|
|
|
@@ -20,20 +20,20 @@ class RpcClientImpl {
|
|
|
20
20
|
if (cached !== undefined) {
|
|
21
21
|
consumer(cached);
|
|
22
22
|
}
|
|
23
|
-
//
|
|
23
|
+
// Add subscription before subscribing in case in will be unsubscribed while waiting for a server reply
|
|
24
|
+
// Subscription is added in pending state to not re-subscribe until subscribe response is completed
|
|
24
25
|
this.remoteSubscriptions.addSubscription(itemName, parameters, consumer);
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
await this.connection.connect();
|
|
26
|
+
// Start connecting, if not already
|
|
27
|
+
void this.connection.connect();
|
|
28
28
|
try {
|
|
29
|
-
// check if already unsubscribed
|
|
30
|
-
const sub = this.remoteSubscriptions.getConsumerSubscription(itemName, parameters, consumer);
|
|
31
|
-
if (!sub)
|
|
32
|
-
return;
|
|
33
|
-
// mark as completed - will resubscribe on reconnects
|
|
34
|
-
sub.completed = true;
|
|
35
29
|
this.remoteSubscriptions.pause(itemName, parameters);
|
|
36
30
|
const data = await this.invoke(itemName, rpc_js_1.InvocationType.Subscribe, (...parameters) => this.httpClient.subscribe(itemName, parameters, callOptions?.timeout ?? this.options.callTimeout), parameters);
|
|
31
|
+
// check if still subscribed
|
|
32
|
+
const sub = this.remoteSubscriptions.getConsumerSubscription(itemName, parameters, consumer);
|
|
33
|
+
if (sub) {
|
|
34
|
+
// mark as completed - will resubscribe on reconnects
|
|
35
|
+
sub.completed = true;
|
|
36
|
+
}
|
|
37
37
|
this.remoteSubscriptions.unpause(itemName, parameters);
|
|
38
38
|
this.remoteSubscriptions.consume(itemName, parameters, data);
|
|
39
39
|
this.remoteSubscriptions.flushQueue(itemName, parameters);
|
|
@@ -59,6 +59,7 @@ class RpcClientImpl {
|
|
|
59
59
|
this.remoteSubscriptions.consume(itemName, params, data);
|
|
60
60
|
})
|
|
61
61
|
.catch((e) => {
|
|
62
|
+
// is it a good idea to unsubscribe on errors? What if those errors are network-related?
|
|
62
63
|
for (const consumer of consumers) {
|
|
63
64
|
this.remoteSubscriptions.unsubscribe(itemName, params, consumer);
|
|
64
65
|
}
|
|
@@ -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;QA0ClC,aAAQ,GAAG,IAAA,eAAM,GAAE,CAAA;QA8C3B,SAAI,GAAG,CACb,QAAgB,EAChB,UAAqB,EACrB,WAAyB,EACP,EAAE;YACpB,OAAO,IAAI,CAAC,MAAM,CAChB,QAAQ,EACR,uBAAc,CAAC,IAAI,EACnB,CAAC,GAAG,UAAU,EAAE,EAAE,CAChB,IAAI,CAAC,UAAU,CAAC,IAAI,CAClB,QAAQ,EACR,UAAU,EACV,WAAW,EAAE,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CACjD,EACH,UAAU,CACX,CAAA;QACH,CAAC,CAAA;QAEO,cAAS,GAAG,KAAK,EACvB,QAAgB,EAChB,UAAqB,EACrB,QAA8B,EAC9B,WAAyB,EACV,EAAE;YACjB,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;YAEvE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,QAAQ,CAAC,MAAM,CAAC,CAAA;YAClB,CAAC;YAED,
|
|
1
|
+
{"version":3,"file":"RpcClientImpl.js","sourceRoot":"","sources":["../../src/client/RpcClientImpl.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,6 @@ export declare class RpcServerImpl<S extends Services<S>, C extends RpcContext>
|
|
|
13
13
|
createServicesWithTriggers(): ServicesWithTriggers<S>;
|
|
14
14
|
_allSubscriptions(): [itemName: string, parameters: unknown[], consumer: unknown][];
|
|
15
15
|
private readonly localSubscriptions;
|
|
16
|
-
private readonly invocationCache;
|
|
17
16
|
private connectionsServer;
|
|
18
17
|
readonly httpServer: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
|
|
19
18
|
private call;
|
|
@@ -29,7 +29,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
exports.RpcServerImpl = void 0;
|
|
30
30
|
const LocalSubscriptions_js_1 = require("./LocalSubscriptions.js");
|
|
31
31
|
const http_1 = __importDefault(require("http"));
|
|
32
|
-
const promises_js_1 = require("../utils/promises.js");
|
|
33
32
|
const http_js_1 = require("./http.js");
|
|
34
33
|
const rpc_js_1 = require("../rpc.js");
|
|
35
34
|
const logger_js_1 = require("../logger.js");
|
|
@@ -41,7 +40,6 @@ class RpcServerImpl {
|
|
|
41
40
|
this.services = services;
|
|
42
41
|
this.options = options;
|
|
43
42
|
this.localSubscriptions = new LocalSubscriptions_js_1.LocalSubscriptions();
|
|
44
|
-
this.invocationCache = new promises_js_1.PromiseCache();
|
|
45
43
|
this.connectionsServer = null;
|
|
46
44
|
this.call = async (connectionContext, itemName, parameters) => {
|
|
47
45
|
const item = this.getRemoteFunction(itemName);
|
|
@@ -184,16 +182,14 @@ class RpcServerImpl {
|
|
|
184
182
|
};
|
|
185
183
|
}
|
|
186
184
|
invokeLocalFunction(connectionContext, itemName, item, parameters, invocationType) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return (0, middleware_js_1.withMiddlewares)(ctx, this.options.middleware, invokeItem, ...parametersCopy);
|
|
196
|
-
});
|
|
185
|
+
const parametersCopy = (0, json_js_1.safeParseJson)((0, json_js_1.safeStringify)(parameters));
|
|
186
|
+
const ctx = (0, json_js_1.safeParseJson)((0, json_js_1.safeStringify)(connectionContext));
|
|
187
|
+
ctx.itemName = itemName;
|
|
188
|
+
ctx.invocationType = invocationType;
|
|
189
|
+
const invokeItem = (...params) => {
|
|
190
|
+
return item.function.call(item.container, ...params, ctx);
|
|
191
|
+
};
|
|
192
|
+
return (0, middleware_js_1.withMiddlewares)(ctx, this.options.middleware, invokeItem, ...parametersCopy);
|
|
197
193
|
}
|
|
198
194
|
}
|
|
199
195
|
exports.RpcServerImpl = RpcServerImpl;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RpcServerImpl.js","sourceRoot":"","sources":["../../src/server/RpcServerImpl.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,mEAA0D;AAC1D,gDAAuB;AAEvB,
|
|
1
|
+
{"version":3,"file":"RpcServerImpl.js","sourceRoot":"","sources":["../../src/server/RpcServerImpl.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/promises.d.ts
CHANGED
package/dist/utils/promises.js
CHANGED
|
@@ -1,27 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.adelay =
|
|
4
|
-
class PromiseCache {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.cache = {};
|
|
7
|
-
}
|
|
8
|
-
invoke(cacheKey, supplier) {
|
|
9
|
-
const key = JSON.stringify(cacheKey);
|
|
10
|
-
if (!this.cache[key]) {
|
|
11
|
-
this.cache[key] = supplier()
|
|
12
|
-
.then((r) => {
|
|
13
|
-
delete this.cache[key];
|
|
14
|
-
return r;
|
|
15
|
-
})
|
|
16
|
-
.catch((e) => {
|
|
17
|
-
delete this.cache[key];
|
|
18
|
-
throw e;
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
return this.cache[key];
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
exports.PromiseCache = PromiseCache;
|
|
3
|
+
exports.adelay = void 0;
|
|
25
4
|
async function adelay(ms) {
|
|
26
5
|
return new Promise((r) => setTimeout(r, ms));
|
|
27
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promises.js","sourceRoot":"","sources":["../../src/utils/promises.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"promises.js","sourceRoot":"","sources":["../../src/utils/promises.ts"],"names":[],"mappings":";;;AAAO,KAAK,UAAU,MAAM,CAAC,EAAU;IACrC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;AAC9C,CAAC;AAFD,wBAEC"}
|
package/package.json
CHANGED
|
@@ -128,21 +128,14 @@ export class RpcClientImpl<S extends Services<S>> implements RpcClient {
|
|
|
128
128
|
consumer(cached)
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
//
|
|
131
|
+
// Add subscription before subscribing in case in will be unsubscribed while waiting for a server reply
|
|
132
|
+
// Subscription is added in pending state to not re-subscribe until subscribe response is completed
|
|
132
133
|
this.remoteSubscriptions.addSubscription(itemName, parameters, consumer)
|
|
133
134
|
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
await this.connection.connect()
|
|
135
|
+
// Start connecting, if not already
|
|
136
|
+
void this.connection.connect()
|
|
137
137
|
|
|
138
138
|
try {
|
|
139
|
-
// check if already unsubscribed
|
|
140
|
-
const sub = this.remoteSubscriptions.getConsumerSubscription(itemName, parameters, consumer)
|
|
141
|
-
if (!sub) return
|
|
142
|
-
|
|
143
|
-
// mark as completed - will resubscribe on reconnects
|
|
144
|
-
sub.completed = true
|
|
145
|
-
|
|
146
139
|
this.remoteSubscriptions.pause(itemName, parameters)
|
|
147
140
|
|
|
148
141
|
const data = await this.invoke(
|
|
@@ -157,7 +150,15 @@ export class RpcClientImpl<S extends Services<S>> implements RpcClient {
|
|
|
157
150
|
parameters,
|
|
158
151
|
)
|
|
159
152
|
|
|
153
|
+
// check if still subscribed
|
|
154
|
+
const sub = this.remoteSubscriptions.getConsumerSubscription(itemName, parameters, consumer)
|
|
155
|
+
if (sub) {
|
|
156
|
+
// mark as completed - will resubscribe on reconnects
|
|
157
|
+
sub.completed = true
|
|
158
|
+
}
|
|
159
|
+
|
|
160
160
|
this.remoteSubscriptions.unpause(itemName, parameters)
|
|
161
|
+
|
|
161
162
|
this.remoteSubscriptions.consume(itemName, parameters, data)
|
|
162
163
|
this.remoteSubscriptions.flushQueue(itemName, parameters)
|
|
163
164
|
} catch (e) {
|
|
@@ -199,6 +200,7 @@ export class RpcClientImpl<S extends Services<S>> implements RpcClient {
|
|
|
199
200
|
this.remoteSubscriptions.consume(itemName, params, data)
|
|
200
201
|
})
|
|
201
202
|
.catch((e) => {
|
|
203
|
+
// is it a good idea to unsubscribe on errors? What if those errors are network-related?
|
|
202
204
|
for (const consumer of consumers) {
|
|
203
205
|
this.remoteSubscriptions.unsubscribe(itemName, params, consumer)
|
|
204
206
|
}
|
|
@@ -8,7 +8,7 @@ export class ConnectionsServer {
|
|
|
8
8
|
server: http.Server,
|
|
9
9
|
options: ConnectionsServerOptions,
|
|
10
10
|
connectionClosed: (clientId: string) => void,
|
|
11
|
-
closeSocketsWithDifferentPath: boolean
|
|
11
|
+
closeSocketsWithDifferentPath: boolean,
|
|
12
12
|
) {
|
|
13
13
|
this.wss = new WebSocketServer({noServer: true})
|
|
14
14
|
|
|
@@ -2,7 +2,6 @@ import {PublishServicesOptions, RpcServer} from "./index.js"
|
|
|
2
2
|
import {LocalSubscriptions} from "./LocalSubscriptions.js"
|
|
3
3
|
import http from "http"
|
|
4
4
|
import type {ConnectionsServer} from "./ConnectionsServer.js"
|
|
5
|
-
import {PromiseCache} from "../utils/promises.js"
|
|
6
5
|
import {serveHttpRequest} from "./http.js"
|
|
7
6
|
import {
|
|
8
7
|
InvocationType,
|
|
@@ -21,7 +20,7 @@ import {safeParseJson, safeStringify} from "../utils/json.js"
|
|
|
21
20
|
export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implements RpcServer {
|
|
22
21
|
constructor(
|
|
23
22
|
private readonly services: S,
|
|
24
|
-
private readonly options: PublishServicesOptions<C
|
|
23
|
+
private readonly options: PublishServicesOptions<C>,
|
|
25
24
|
) {
|
|
26
25
|
if ("server" in this.options) {
|
|
27
26
|
this.httpServer = this.options.server
|
|
@@ -50,7 +49,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
50
49
|
res,
|
|
51
50
|
options.path,
|
|
52
51
|
options.createServerHooks ? options.createServerHooks(hooks, req) : hooks,
|
|
53
|
-
options.createConnectionContext
|
|
52
|
+
options.createConnectionContext,
|
|
54
53
|
).catch((e) => {
|
|
55
54
|
log.warn("Unhandled error serving HTTP request", e)
|
|
56
55
|
})
|
|
@@ -66,7 +65,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
66
65
|
(clientId) => {
|
|
67
66
|
this.localSubscriptions.unsubscribeAll(clientId)
|
|
68
67
|
},
|
|
69
|
-
!("server" in this.options)
|
|
68
|
+
!("server" in this.options),
|
|
70
69
|
)
|
|
71
70
|
}
|
|
72
71
|
|
|
@@ -114,14 +113,13 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
114
113
|
}
|
|
115
114
|
|
|
116
115
|
private readonly localSubscriptions = new LocalSubscriptions()
|
|
117
|
-
private readonly invocationCache = new PromiseCache()
|
|
118
116
|
private connectionsServer: ConnectionsServer | null = null
|
|
119
117
|
readonly httpServer
|
|
120
118
|
|
|
121
119
|
private call = async (
|
|
122
120
|
connectionContext: RpcConnectionContext,
|
|
123
121
|
itemName: string,
|
|
124
|
-
parameters: unknown[]
|
|
122
|
+
parameters: unknown[],
|
|
125
123
|
): Promise<unknown> => {
|
|
126
124
|
const item = this.getRemoteFunction(itemName)
|
|
127
125
|
|
|
@@ -135,7 +133,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
135
133
|
itemName,
|
|
136
134
|
item,
|
|
137
135
|
parameters,
|
|
138
|
-
InvocationType.Call
|
|
136
|
+
InvocationType.Call,
|
|
139
137
|
)
|
|
140
138
|
} catch (e) {
|
|
141
139
|
log.error(`Cannot call item ${itemName}.`, e)
|
|
@@ -146,7 +144,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
146
144
|
private subscribe = async (
|
|
147
145
|
connectionContext: RpcConnectionContext,
|
|
148
146
|
itemName: string,
|
|
149
|
-
parameters: unknown[]
|
|
147
|
+
parameters: unknown[],
|
|
150
148
|
) => {
|
|
151
149
|
const item = this.getRemoteFunction(itemName)
|
|
152
150
|
|
|
@@ -167,7 +165,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
167
165
|
itemName,
|
|
168
166
|
item,
|
|
169
167
|
parameters,
|
|
170
|
-
InvocationType.Trigger
|
|
168
|
+
InvocationType.Trigger,
|
|
171
169
|
)
|
|
172
170
|
|
|
173
171
|
const newDataJson = safeStringify(newData)
|
|
@@ -178,7 +176,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
178
176
|
connectionContext.clientId,
|
|
179
177
|
itemName,
|
|
180
178
|
parameters,
|
|
181
|
-
newData
|
|
179
|
+
newData,
|
|
182
180
|
)
|
|
183
181
|
}
|
|
184
182
|
} catch (e) {
|
|
@@ -193,7 +191,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
193
191
|
itemName,
|
|
194
192
|
item,
|
|
195
193
|
parameters,
|
|
196
|
-
InvocationType.Subscribe
|
|
194
|
+
InvocationType.Subscribe,
|
|
197
195
|
)
|
|
198
196
|
lastDataJson = safeStringify(lastData)
|
|
199
197
|
|
|
@@ -209,7 +207,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
209
207
|
private unsubscribe = async (
|
|
210
208
|
connectionContext: RpcConnectionContext,
|
|
211
209
|
itemName: string,
|
|
212
|
-
parameters: unknown[]
|
|
210
|
+
parameters: unknown[],
|
|
213
211
|
) => {
|
|
214
212
|
try {
|
|
215
213
|
this.localSubscriptions.unsubscribe(connectionContext.clientId, itemName, parameters)
|
|
@@ -221,7 +219,7 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
221
219
|
|
|
222
220
|
private getRemoteFunction(
|
|
223
221
|
itemName: string,
|
|
224
|
-
root: any = this.services
|
|
222
|
+
root: any = this.services,
|
|
225
223
|
): {function: RemoteFunction; container: any} | undefined {
|
|
226
224
|
const parts = itemName.split("/")
|
|
227
225
|
|
|
@@ -248,22 +246,18 @@ export class RpcServerImpl<S extends Services<S>, C extends RpcContext> implemen
|
|
|
248
246
|
itemName: string,
|
|
249
247
|
item: {function: RemoteFunction; container: any},
|
|
250
248
|
parameters: unknown[],
|
|
251
|
-
invocationType: InvocationType
|
|
249
|
+
invocationType: InvocationType,
|
|
252
250
|
): Promise<unknown> {
|
|
253
|
-
|
|
254
|
-
{clientId: connectionContext.clientId, itemName, parameters},
|
|
255
|
-
() => {
|
|
256
|
-
const parametersCopy: unknown[] = safeParseJson(safeStringify(parameters))
|
|
251
|
+
const parametersCopy: unknown[] = safeParseJson(safeStringify(parameters))
|
|
257
252
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
253
|
+
const ctx = safeParseJson(safeStringify(connectionContext)) as C
|
|
254
|
+
ctx.itemName = itemName
|
|
255
|
+
ctx.invocationType = invocationType
|
|
261
256
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
)
|
|
257
|
+
const invokeItem = (...params: unknown[]) => {
|
|
258
|
+
return item.function.call(item.container, ...params, ctx)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return withMiddlewares<C>(ctx, this.options.middleware, invokeItem, ...parametersCopy)
|
|
268
262
|
}
|
|
269
263
|
}
|
package/src/utils/promises.ts
CHANGED
|
@@ -1,25 +1,3 @@
|
|
|
1
|
-
export class PromiseCache {
|
|
2
|
-
invoke<T>(cacheKey: unknown, supplier: () => Promise<T>): Promise<T> {
|
|
3
|
-
const key = JSON.stringify(cacheKey)
|
|
4
|
-
|
|
5
|
-
if (!this.cache[key]) {
|
|
6
|
-
this.cache[key] = supplier()
|
|
7
|
-
.then((r) => {
|
|
8
|
-
delete this.cache[key]
|
|
9
|
-
return r
|
|
10
|
-
})
|
|
11
|
-
.catch((e) => {
|
|
12
|
-
delete this.cache[key]
|
|
13
|
-
throw e
|
|
14
|
-
})
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return this.cache[key]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
private cache: {[key: string]: Promise<any>} = {}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
1
|
export async function adelay(ms: number) {
|
|
24
2
|
return new Promise((r) => setTimeout(r, ms))
|
|
25
3
|
}
|
package/tests/calls.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {assert} from "chai"
|
|
2
2
|
import {createTestClient, startTestServer} from "./testUtils.js"
|
|
3
|
-
import {CallOptions,
|
|
3
|
+
import {CallOptions, RpcErrors} from "../src/index.js"
|
|
4
4
|
import {adelay} from "../src/utils/promises.js"
|
|
5
5
|
|
|
6
6
|
describe("calls", () => {
|
|
@@ -169,41 +169,6 @@ describe("calls", () => {
|
|
|
169
169
|
const r = await client.obj.hello()
|
|
170
170
|
assert.equal("yes", r)
|
|
171
171
|
})
|
|
172
|
-
|
|
173
|
-
it("concurrent call cache", async () => {
|
|
174
|
-
const item = {r: "1"}
|
|
175
|
-
let supplied = 0
|
|
176
|
-
|
|
177
|
-
const server = {
|
|
178
|
-
test: {
|
|
179
|
-
item: async () => {
|
|
180
|
-
await adelay(1)
|
|
181
|
-
supplied++
|
|
182
|
-
return item
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
await startTestServer(server)
|
|
188
|
-
|
|
189
|
-
const client = await createTestClient<typeof server>()
|
|
190
|
-
|
|
191
|
-
let item1
|
|
192
|
-
client.test.item().then((item) => {
|
|
193
|
-
item1 = item
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
let item2
|
|
197
|
-
client.test.item().then((item) => {
|
|
198
|
-
item2 = item
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
await adelay(50)
|
|
202
|
-
assert.deepEqual(item1, item)
|
|
203
|
-
assert.deepEqual(item2, item)
|
|
204
|
-
|
|
205
|
-
assert.equal(supplied, 1)
|
|
206
|
-
})
|
|
207
172
|
})
|
|
208
173
|
|
|
209
174
|
abstract class A {
|
package/tests/middleware.ts
CHANGED
|
@@ -44,7 +44,7 @@ describe("middleware", () => {
|
|
|
44
44
|
return next()
|
|
45
45
|
},
|
|
46
46
|
],
|
|
47
|
-
}
|
|
47
|
+
},
|
|
48
48
|
)
|
|
49
49
|
|
|
50
50
|
const remote = await createTestClient<typeof services>()
|
|
@@ -128,6 +128,7 @@ describe("middleware", () => {
|
|
|
128
128
|
return next((r as number) + 1)
|
|
129
129
|
},
|
|
130
130
|
],
|
|
131
|
+
connectOnCreate: true,
|
|
131
132
|
})
|
|
132
133
|
|
|
133
134
|
let response
|
|
@@ -135,9 +136,12 @@ describe("middleware", () => {
|
|
|
135
136
|
(r) => {
|
|
136
137
|
response = r
|
|
137
138
|
},
|
|
138
|
-
{param: 1}
|
|
139
|
+
{param: 1},
|
|
139
140
|
)
|
|
140
141
|
|
|
142
|
+
assert.equal(response, 1)
|
|
143
|
+
assert.equal(count, 2)
|
|
144
|
+
|
|
141
145
|
services.remote.trigger({param: 1})
|
|
142
146
|
|
|
143
147
|
await adelay(20)
|
|
@@ -172,6 +176,7 @@ describe("middleware", () => {
|
|
|
172
176
|
throw new Error("Test error")
|
|
173
177
|
},
|
|
174
178
|
],
|
|
179
|
+
connectOnCreate: true,
|
|
175
180
|
})
|
|
176
181
|
|
|
177
182
|
await client.remote.subscribe((r) => {
|
|
@@ -227,7 +232,7 @@ describe("middleware", () => {
|
|
|
227
232
|
throw new Error("Error")
|
|
228
233
|
},
|
|
229
234
|
],
|
|
230
|
-
}
|
|
235
|
+
},
|
|
231
236
|
)
|
|
232
237
|
|
|
233
238
|
const client = await createTestClient<typeof services>({})
|
package/tests/subscriptions.ts
CHANGED
|
@@ -140,41 +140,6 @@ describe("Subscriptions", () => {
|
|
|
140
140
|
assert.equal(testServer?._allSubscriptions()[0][0], "test/item")
|
|
141
141
|
})
|
|
142
142
|
|
|
143
|
-
it("concurrent subscribe cache", async () => {
|
|
144
|
-
const item = {r: "1"}
|
|
145
|
-
let supplied = 0
|
|
146
|
-
|
|
147
|
-
const server = {
|
|
148
|
-
test: {
|
|
149
|
-
item: async () => {
|
|
150
|
-
await adelay(20)
|
|
151
|
-
supplied++
|
|
152
|
-
return item
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
await startTestServer(server)
|
|
158
|
-
|
|
159
|
-
const client = await createTestClient<typeof server>()
|
|
160
|
-
|
|
161
|
-
let item1
|
|
162
|
-
client.test.item.subscribe((item) => {
|
|
163
|
-
item1 = item
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
let item2
|
|
167
|
-
client.test.item.subscribe((item) => {
|
|
168
|
-
item2 = item
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
await adelay(50)
|
|
172
|
-
assert.deepEqual(item1, item)
|
|
173
|
-
assert.deepEqual(item2, item)
|
|
174
|
-
|
|
175
|
-
assert.equal(supplied, 1)
|
|
176
|
-
})
|
|
177
|
-
|
|
178
143
|
it("subscribe use client cached value", async () => {
|
|
179
144
|
const item = {r: "1"}
|
|
180
145
|
|
|
@@ -482,23 +447,7 @@ describe("Subscriptions", () => {
|
|
|
482
447
|
})
|
|
483
448
|
|
|
484
449
|
// delay client connection open by 10ms
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
oldAddEL = WebSocket.prototype.addEventListener
|
|
488
|
-
WebSocket.prototype.addEventListener = function (eventName: any, callback: any) {
|
|
489
|
-
if (eventName == "open") {
|
|
490
|
-
oldAddEL.apply(this, [
|
|
491
|
-
eventName,
|
|
492
|
-
() => {
|
|
493
|
-
setTimeout(callback, 10)
|
|
494
|
-
},
|
|
495
|
-
])
|
|
496
|
-
|
|
497
|
-
return
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
return oldAddEL.apply(this, [eventName, callback])
|
|
501
|
-
}
|
|
450
|
+
delayWebsocketConnection(10)
|
|
502
451
|
|
|
503
452
|
const client = await createTestClient<typeof services>()
|
|
504
453
|
|
|
@@ -514,7 +463,7 @@ describe("Subscriptions", () => {
|
|
|
514
463
|
assert.equal(testClient!._allSubscriptions().length, 0)
|
|
515
464
|
assert.equal(testServer!._allSubscriptions().length, 0)
|
|
516
465
|
|
|
517
|
-
|
|
466
|
+
cancelWebsocketConnectionDelay()
|
|
518
467
|
})
|
|
519
468
|
|
|
520
469
|
it("skip unchanged data", async () => {
|
|
@@ -587,6 +536,7 @@ describe("Subscriptions", () => {
|
|
|
587
536
|
|
|
588
537
|
const client = await createTestClient<typeof services>({
|
|
589
538
|
callTimeout: 2 * delay,
|
|
539
|
+
connectOnCreate: true,
|
|
590
540
|
})
|
|
591
541
|
|
|
592
542
|
let received = 0
|
|
@@ -605,6 +555,8 @@ describe("Subscriptions", () => {
|
|
|
605
555
|
assert.equal(received, 2)
|
|
606
556
|
})
|
|
607
557
|
|
|
558
|
+
// Currently not working, b/c paused is boolean
|
|
559
|
+
// To implement it, need to replace it with counter
|
|
608
560
|
it.skip("two concurrent subscribes and trigger", async () => {
|
|
609
561
|
const delay = 50
|
|
610
562
|
|
|
@@ -694,62 +646,82 @@ describe("Subscriptions", () => {
|
|
|
694
646
|
assert.equal(received, 1)
|
|
695
647
|
})
|
|
696
648
|
|
|
697
|
-
it("subscribe
|
|
698
|
-
const
|
|
649
|
+
it("can subscribe while disconnected", async () => {
|
|
650
|
+
const item = {r: "1"}
|
|
699
651
|
|
|
700
|
-
|
|
701
|
-
let serverCalled = 0
|
|
652
|
+
delayWebsocketConnection(50)
|
|
702
653
|
|
|
703
|
-
const services = await startTestServer(
|
|
704
|
-
{
|
|
705
|
-
|
|
706
|
-
async op(params: {key: number}): Promise<number> {
|
|
707
|
-
serverCalled++
|
|
708
|
-
return 1
|
|
709
|
-
},
|
|
710
|
-
},
|
|
654
|
+
const services = await startTestServer({
|
|
655
|
+
test: {
|
|
656
|
+
item: async () => item,
|
|
711
657
|
},
|
|
712
|
-
|
|
713
|
-
async createConnectionContext(req: IncomingMessage): Promise<RpcConnectionContext> {
|
|
714
|
-
const header = req.headers[CLIENT_ID_HEADER]
|
|
715
|
-
|
|
716
|
-
connectedClients++
|
|
658
|
+
})
|
|
717
659
|
|
|
718
|
-
|
|
719
|
-
clientId: (Array.isArray(header) ? header[0] : header) || "anon",
|
|
720
|
-
}
|
|
721
|
-
},
|
|
722
|
-
},
|
|
723
|
-
)
|
|
660
|
+
const remote = await createTestClient<typeof services>()
|
|
724
661
|
|
|
725
|
-
|
|
726
|
-
|
|
662
|
+
let receivedItem
|
|
663
|
+
await remote.test.item.subscribe((item) => {
|
|
664
|
+
receivedItem = item
|
|
727
665
|
})
|
|
728
666
|
|
|
729
|
-
|
|
730
|
-
let received2
|
|
667
|
+
assert.deepEqual(receivedItem, item)
|
|
731
668
|
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
)
|
|
669
|
+
// trigger sends item
|
|
670
|
+
item.r = "2"
|
|
671
|
+
services.test.item.trigger()
|
|
672
|
+
await adelay(60)
|
|
673
|
+
assert.deepEqual(receivedItem, item)
|
|
738
674
|
|
|
739
|
-
|
|
675
|
+
cancelWebsocketConnectionDelay()
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
it("connect during subscribe", async () => {
|
|
679
|
+
const item = {r: "1"}
|
|
740
680
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
681
|
+
delayWebsocketConnection(30)
|
|
682
|
+
|
|
683
|
+
const services = await startTestServer({
|
|
684
|
+
test: {
|
|
685
|
+
item: async () => {
|
|
686
|
+
await adelay(50)
|
|
687
|
+
return item
|
|
688
|
+
},
|
|
744
689
|
},
|
|
745
|
-
|
|
746
|
-
)
|
|
690
|
+
})
|
|
747
691
|
|
|
748
|
-
await
|
|
692
|
+
const remote = await createTestClient<typeof services>()
|
|
693
|
+
|
|
694
|
+
let receivedItem
|
|
695
|
+
await remote.test.item.subscribe((item) => {
|
|
696
|
+
receivedItem = item
|
|
697
|
+
})
|
|
698
|
+
|
|
699
|
+
assert.deepEqual(receivedItem, item)
|
|
749
700
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
701
|
+
// trigger sends item
|
|
702
|
+
item.r = "2"
|
|
703
|
+
services.test.item.trigger()
|
|
704
|
+
await adelay(100)
|
|
705
|
+
assert.deepEqual(receivedItem, item)
|
|
706
|
+
|
|
707
|
+
cancelWebsocketConnectionDelay()
|
|
754
708
|
})
|
|
755
709
|
})
|
|
710
|
+
|
|
711
|
+
let oldAddEL: typeof WebSocket.prototype.addEventListener
|
|
712
|
+
|
|
713
|
+
function delayWebsocketConnection(ms: number) {
|
|
714
|
+
oldAddEL = WebSocket.prototype.addEventListener
|
|
715
|
+
WebSocket.prototype.addEventListener = function (eventName: any, callback: any) {
|
|
716
|
+
oldAddEL.apply(this, [
|
|
717
|
+
eventName,
|
|
718
|
+
(...args) => {
|
|
719
|
+
setTimeout(() => callback(...args), ms)
|
|
720
|
+
},
|
|
721
|
+
])
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
function cancelWebsocketConnectionDelay() {
|
|
726
|
+
WebSocket.prototype.addEventListener = oldAddEL
|
|
727
|
+
}
|
package/tests/triggers.ts
CHANGED
|
@@ -22,7 +22,9 @@ describe("Subscription triggers", () => {
|
|
|
22
22
|
timeout: 0,
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
const remote = await createTestClient<typeof services>(
|
|
25
|
+
const remote = await createTestClient<typeof services>({
|
|
26
|
+
connectOnCreate: true,
|
|
27
|
+
})
|
|
26
28
|
|
|
27
29
|
let item1
|
|
28
30
|
let item2
|
|
@@ -68,7 +70,9 @@ describe("Subscription triggers", () => {
|
|
|
68
70
|
timeout: throttleTimeout,
|
|
69
71
|
})
|
|
70
72
|
|
|
71
|
-
const remote = await createTestClient<typeof services>(
|
|
73
|
+
const remote = await createTestClient<typeof services>({
|
|
74
|
+
connectOnCreate: true,
|
|
75
|
+
})
|
|
72
76
|
|
|
73
77
|
let count = 0
|
|
74
78
|
let item = null
|