@dxos/rpc 2.33.9-dev.d0ae5f95 → 2.33.9-dev.d0dce35f
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/dist/src/proto/gen/dxos/rpc/test.d.ts +32 -4
- package/dist/src/proto/gen/dxos/rpc/test.d.ts.map +1 -1
- package/dist/src/proto/gen/dxos/rpc.d.ts +58 -8
- package/dist/src/proto/gen/dxos/rpc.d.ts.map +1 -1
- package/dist/src/proto/gen/dxos/rpc.js +4 -0
- package/dist/src/proto/gen/dxos/rpc.js.map +1 -1
- package/dist/src/proto/gen/google/protobuf.d.ts +2 -2
- package/dist/src/proto/gen/google/protobuf.d.ts.map +1 -1
- package/dist/src/proto/gen/index.d.ts.map +1 -1
- package/dist/src/proto/gen/index.js +1 -1
- package/dist/src/proto/gen/index.js.map +1 -1
- package/dist/src/rpc.d.ts.map +1 -1
- package/dist/src/rpc.js +43 -13
- package/dist/src/rpc.js.map +1 -1
- package/dist/src/rpc.test.js +102 -45
- package/dist/src/rpc.test.js.map +1 -1
- package/dist/src/service.d.ts.map +1 -1
- package/dist/src/service.js +13 -7
- package/dist/src/service.js.map +1 -1
- package/dist/src/service.test.js +1 -0
- package/dist/src/service.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/proto/gen/dxos/rpc/test.ts +32 -4
- package/src/proto/gen/dxos/rpc.ts +58 -8
- package/src/proto/gen/google/protobuf.ts +2 -2
- package/src/proto/gen/index.ts +1 -1
- package/src/rpc.test.ts +113 -45
- package/src/rpc.ts +49 -15
- package/src/service.test.ts +1 -0
- package/src/service.ts +15 -7
package/src/rpc.test.ts
CHANGED
@@ -13,17 +13,22 @@ import { Any } from './proto/gen/google/protobuf';
|
|
13
13
|
import { RpcPeer } from './rpc';
|
14
14
|
import { createLinkedPorts } from './testutil';
|
15
15
|
|
16
|
+
const createPayload = (value = ''): Any => ({
|
17
|
+
type_url: '',
|
18
|
+
value: Buffer.from(value)
|
19
|
+
});
|
20
|
+
|
16
21
|
describe('RpcPeer', () => {
|
17
22
|
describe('handshake', () => {
|
18
23
|
test('can open', async () => {
|
19
24
|
const [alicePort, bobPort] = createLinkedPorts();
|
20
25
|
|
21
26
|
const alice = new RpcPeer({
|
22
|
-
messageHandler: async msg => (
|
27
|
+
messageHandler: async msg => createPayload(),
|
23
28
|
port: alicePort
|
24
29
|
});
|
25
30
|
const bob = new RpcPeer({
|
26
|
-
messageHandler: async msg => (
|
31
|
+
messageHandler: async msg => createPayload(),
|
27
32
|
port: bobPort
|
28
33
|
});
|
29
34
|
|
@@ -36,11 +41,11 @@ describe('RpcPeer', () => {
|
|
36
41
|
test('open waits for the other peer to call open', async () => {
|
37
42
|
const [alicePort, bobPort] = createLinkedPorts();
|
38
43
|
const alice: RpcPeer = new RpcPeer({
|
39
|
-
messageHandler: async msg => (
|
44
|
+
messageHandler: async msg => createPayload(),
|
40
45
|
port: alicePort
|
41
46
|
});
|
42
47
|
const bob = new RpcPeer({
|
43
|
-
messageHandler: async msg => (
|
48
|
+
messageHandler: async msg => createPayload(),
|
44
49
|
port: bobPort
|
45
50
|
});
|
46
51
|
|
@@ -64,7 +69,7 @@ describe('RpcPeer', () => {
|
|
64
69
|
const [alicePort, bobPort] = createLinkedPorts();
|
65
70
|
|
66
71
|
const alice: RpcPeer = new RpcPeer({
|
67
|
-
messageHandler: async msg => (
|
72
|
+
messageHandler: async msg => createPayload(),
|
68
73
|
port: alicePort
|
69
74
|
});
|
70
75
|
const aliceOpen = alice.open();
|
@@ -72,7 +77,7 @@ describe('RpcPeer', () => {
|
|
72
77
|
await sleep(5);
|
73
78
|
|
74
79
|
const bob = new RpcPeer({
|
75
|
-
messageHandler: async msg => (
|
80
|
+
messageHandler: async msg => createPayload(),
|
76
81
|
port: bobPort
|
77
82
|
});
|
78
83
|
|
@@ -88,7 +93,7 @@ describe('RpcPeer', () => {
|
|
88
93
|
let portOpen = false;
|
89
94
|
|
90
95
|
const alice: RpcPeer = new RpcPeer({
|
91
|
-
messageHandler: async msg => (
|
96
|
+
messageHandler: async msg => createPayload(),
|
92
97
|
port: {
|
93
98
|
send: msg => {
|
94
99
|
portOpen && alicePort.send(msg);
|
@@ -98,7 +103,7 @@ describe('RpcPeer', () => {
|
|
98
103
|
});
|
99
104
|
|
100
105
|
const bob = new RpcPeer({
|
101
|
-
messageHandler: async msg => (
|
106
|
+
messageHandler: async msg => createPayload(),
|
102
107
|
port: {
|
103
108
|
send: msg => {
|
104
109
|
portOpen && bobPort.send(msg);
|
@@ -123,7 +128,7 @@ describe('RpcPeer', () => {
|
|
123
128
|
const [alicePort, bobPort] = createLinkedPorts();
|
124
129
|
|
125
130
|
const alice: RpcPeer = new RpcPeer({
|
126
|
-
messageHandler: async msg => (
|
131
|
+
messageHandler: async msg => createPayload(),
|
127
132
|
port: {
|
128
133
|
send: msg => { },
|
129
134
|
subscribe: alicePort.subscribe
|
@@ -131,7 +136,7 @@ describe('RpcPeer', () => {
|
|
131
136
|
});
|
132
137
|
|
133
138
|
const bob = new RpcPeer({
|
134
|
-
messageHandler: async msg => (
|
139
|
+
messageHandler: async msg => createPayload(),
|
135
140
|
port: bobPort
|
136
141
|
});
|
137
142
|
|
@@ -160,12 +165,12 @@ describe('RpcPeer', () => {
|
|
160
165
|
messageHandler: async (method, msg) => {
|
161
166
|
expect(method).toEqual('method');
|
162
167
|
expect(msg.value).toEqual(Buffer.from('request'));
|
163
|
-
return
|
168
|
+
return createPayload('response');
|
164
169
|
},
|
165
170
|
port: alicePort
|
166
171
|
});
|
167
172
|
const bob = new RpcPeer({
|
168
|
-
messageHandler: async (method, msg) => (
|
173
|
+
messageHandler: async (method, msg) => createPayload(),
|
169
174
|
port: bobPort
|
170
175
|
});
|
171
176
|
|
@@ -174,8 +179,8 @@ describe('RpcPeer', () => {
|
|
174
179
|
bob.open()
|
175
180
|
]);
|
176
181
|
|
177
|
-
const response = await bob.call('method',
|
178
|
-
expect(response).toEqual(
|
182
|
+
const response = await bob.call('method', createPayload('request'));
|
183
|
+
expect(response).toEqual(createPayload('response'));
|
179
184
|
});
|
180
185
|
|
181
186
|
test('can send multiple requests', async () => {
|
@@ -197,7 +202,7 @@ describe('RpcPeer', () => {
|
|
197
202
|
port: alicePort
|
198
203
|
});
|
199
204
|
const bob = new RpcPeer({
|
200
|
-
messageHandler: async msg => (
|
205
|
+
messageHandler: async msg => createPayload(),
|
201
206
|
port: bobPort
|
202
207
|
});
|
203
208
|
|
@@ -206,14 +211,14 @@ describe('RpcPeer', () => {
|
|
206
211
|
bob.open()
|
207
212
|
]);
|
208
213
|
|
209
|
-
expect((await bob.call('method',
|
214
|
+
expect((await bob.call('method', createPayload('request'))).value).toEqual(Buffer.from('request'));
|
210
215
|
|
211
|
-
const parallel1 = bob.call('method',
|
212
|
-
const parallel2 = bob.call('method',
|
213
|
-
const error = bob.call('method',
|
216
|
+
const parallel1 = bob.call('method', createPayload('p1'));
|
217
|
+
const parallel2 = bob.call('method', createPayload('p2'));
|
218
|
+
const error = bob.call('method', createPayload('error'));
|
214
219
|
|
215
|
-
await expect(await parallel1).toEqual(
|
216
|
-
await expect(await parallel2).toEqual(
|
220
|
+
await expect(await parallel1).toEqual(createPayload('p1'));
|
221
|
+
await expect(await parallel2).toEqual(createPayload('p2'));
|
217
222
|
await expect(error).toBeRejected();
|
218
223
|
});
|
219
224
|
|
@@ -232,7 +237,7 @@ describe('RpcPeer', () => {
|
|
232
237
|
port: alicePort
|
233
238
|
});
|
234
239
|
const bob = new RpcPeer({
|
235
|
-
messageHandler: async msg => (
|
240
|
+
messageHandler: async msg => createPayload(),
|
236
241
|
port: bobPort
|
237
242
|
});
|
238
243
|
|
@@ -243,7 +248,7 @@ describe('RpcPeer', () => {
|
|
243
248
|
|
244
249
|
let error!: Error;
|
245
250
|
try {
|
246
|
-
await bob.call('RpcMethodName',
|
251
|
+
await bob.call('RpcMethodName', createPayload('request'));
|
247
252
|
} catch (err: any) {
|
248
253
|
error = err;
|
249
254
|
}
|
@@ -266,7 +271,7 @@ describe('RpcPeer', () => {
|
|
266
271
|
port: alicePort
|
267
272
|
});
|
268
273
|
const bob = new RpcPeer({
|
269
|
-
messageHandler: async msg => (
|
274
|
+
messageHandler: async msg => createPayload(),
|
270
275
|
port: bobPort
|
271
276
|
});
|
272
277
|
|
@@ -275,7 +280,7 @@ describe('RpcPeer', () => {
|
|
275
280
|
bob.open()
|
276
281
|
]);
|
277
282
|
|
278
|
-
const req = bob.call('method',
|
283
|
+
const req = bob.call('method', createPayload('request'));
|
279
284
|
bob.close();
|
280
285
|
|
281
286
|
await expect(req).toBeRejected();
|
@@ -293,7 +298,7 @@ describe('RpcPeer', () => {
|
|
293
298
|
port: alicePort
|
294
299
|
});
|
295
300
|
const bob = new RpcPeer({
|
296
|
-
messageHandler: async msg => (
|
301
|
+
messageHandler: async msg => createPayload(),
|
297
302
|
port: bobPort,
|
298
303
|
timeout: 50
|
299
304
|
});
|
@@ -304,8 +309,34 @@ describe('RpcPeer', () => {
|
|
304
309
|
]);
|
305
310
|
|
306
311
|
alice.close();
|
307
|
-
const req = bob.call('method',
|
312
|
+
const req = bob.call('method', createPayload('request'));
|
313
|
+
|
314
|
+
await expect(req).toBeRejected();
|
315
|
+
});
|
316
|
+
|
317
|
+
test('requests failing on timeout', async () => {
|
318
|
+
const [alicePort, bobPort] = createLinkedPorts();
|
319
|
+
|
320
|
+
const alice: RpcPeer = new RpcPeer({
|
321
|
+
messageHandler: async (method, msg) => {
|
322
|
+
expect(method).toEqual('method');
|
323
|
+
await sleep(50);
|
324
|
+
return msg;
|
325
|
+
},
|
326
|
+
port: alicePort
|
327
|
+
});
|
328
|
+
const bob = new RpcPeer({
|
329
|
+
messageHandler: async msg => createPayload(),
|
330
|
+
port: bobPort,
|
331
|
+
timeout: 10
|
332
|
+
});
|
308
333
|
|
334
|
+
await Promise.all([
|
335
|
+
alice.open(),
|
336
|
+
bob.open()
|
337
|
+
]);
|
338
|
+
|
339
|
+
const req = bob.call('method', createPayload('request'));
|
309
340
|
await expect(req).toBeRejected();
|
310
341
|
});
|
311
342
|
|
@@ -316,20 +347,20 @@ describe('RpcPeer', () => {
|
|
316
347
|
const [alicePort, bobPort] = createLinkedPorts();
|
317
348
|
|
318
349
|
const alice = new RpcPeer({
|
319
|
-
messageHandler: async msg => (
|
350
|
+
messageHandler: async msg => createPayload(),
|
320
351
|
streamHandler: (method, msg) => {
|
321
352
|
expect(method).toEqual('method');
|
322
353
|
expect(msg.value!).toEqual(Buffer.from('request'));
|
323
354
|
return new Stream<Any>(({ next, close }) => {
|
324
|
-
next(
|
325
|
-
next(
|
355
|
+
next(createPayload('res1'));
|
356
|
+
next(createPayload('res2'));
|
326
357
|
close();
|
327
358
|
});
|
328
359
|
},
|
329
360
|
port: alicePort
|
330
361
|
});
|
331
362
|
const bob = new RpcPeer({
|
332
|
-
messageHandler: async msg => (
|
363
|
+
messageHandler: async msg => createPayload(),
|
333
364
|
port: bobPort
|
334
365
|
});
|
335
366
|
|
@@ -338,12 +369,13 @@ describe('RpcPeer', () => {
|
|
338
369
|
bob.open()
|
339
370
|
]);
|
340
371
|
|
341
|
-
const stream = await bob.callStream('method',
|
372
|
+
const stream = await bob.callStream('method', createPayload('request'));
|
342
373
|
expect(stream).toBeA(Stream);
|
343
374
|
|
344
375
|
expect(await Stream.consume(stream)).toEqual([
|
345
|
-
{
|
346
|
-
{ data:
|
376
|
+
{ ready: true },
|
377
|
+
{ data: createPayload('res1') },
|
378
|
+
{ data: createPayload('res2') },
|
347
379
|
{ closed: true }
|
348
380
|
]);
|
349
381
|
});
|
@@ -352,7 +384,7 @@ describe('RpcPeer', () => {
|
|
352
384
|
const [alicePort, bobPort] = createLinkedPorts();
|
353
385
|
|
354
386
|
const alice = new RpcPeer({
|
355
|
-
messageHandler: async msg => (
|
387
|
+
messageHandler: async msg => createPayload(),
|
356
388
|
streamHandler: (method, msg) => {
|
357
389
|
expect(method).toEqual('method');
|
358
390
|
expect(msg.value).toEqual(Buffer.from('request'));
|
@@ -363,7 +395,7 @@ describe('RpcPeer', () => {
|
|
363
395
|
port: alicePort
|
364
396
|
});
|
365
397
|
const bob = new RpcPeer({
|
366
|
-
messageHandler: async msg => (
|
398
|
+
messageHandler: async msg => createPayload(),
|
367
399
|
port: bobPort
|
368
400
|
});
|
369
401
|
|
@@ -372,7 +404,7 @@ describe('RpcPeer', () => {
|
|
372
404
|
bob.open()
|
373
405
|
]);
|
374
406
|
|
375
|
-
const stream = await bob.callStream('method',
|
407
|
+
const stream = await bob.callStream('method', createPayload('request'));
|
376
408
|
expect(stream).toBeA(Stream);
|
377
409
|
|
378
410
|
const msgs = await Stream.consume(stream);
|
@@ -388,7 +420,7 @@ describe('RpcPeer', () => {
|
|
388
420
|
|
389
421
|
let closeCalled = false;
|
390
422
|
const alice = new RpcPeer({
|
391
|
-
messageHandler: async msg => (
|
423
|
+
messageHandler: async msg => createPayload(),
|
392
424
|
streamHandler: (method, msg) => new Stream<Any>(({ next, close }) => () => {
|
393
425
|
closeCalled = true;
|
394
426
|
}),
|
@@ -396,7 +428,7 @@ describe('RpcPeer', () => {
|
|
396
428
|
});
|
397
429
|
|
398
430
|
const bob = new RpcPeer({
|
399
|
-
messageHandler: async msg => (
|
431
|
+
messageHandler: async msg => createPayload(),
|
400
432
|
port: bobPort
|
401
433
|
});
|
402
434
|
|
@@ -405,13 +437,49 @@ describe('RpcPeer', () => {
|
|
405
437
|
bob.open()
|
406
438
|
]);
|
407
439
|
|
408
|
-
const stream = bob.callStream('method',
|
440
|
+
const stream = bob.callStream('method', createPayload('request'));
|
409
441
|
stream.close();
|
410
442
|
|
411
443
|
await sleep(1);
|
412
444
|
|
413
445
|
expect(closeCalled).toEqual(true);
|
414
446
|
});
|
447
|
+
|
448
|
+
test('reports stream being ready', async () => {
|
449
|
+
const [alicePort, bobPort] = createLinkedPorts();
|
450
|
+
|
451
|
+
const alice = new RpcPeer({
|
452
|
+
messageHandler: async msg => createPayload(),
|
453
|
+
streamHandler: (method, msg) => {
|
454
|
+
expect(method).toEqual('method');
|
455
|
+
expect(msg.value!).toEqual(Buffer.from('request'));
|
456
|
+
return new Stream<Any>(({ ready, close }) => {
|
457
|
+
ready();
|
458
|
+
close();
|
459
|
+
});
|
460
|
+
},
|
461
|
+
port: alicePort
|
462
|
+
});
|
463
|
+
const bob = new RpcPeer({
|
464
|
+
messageHandler: async msg => createPayload(),
|
465
|
+
port: bobPort
|
466
|
+
});
|
467
|
+
|
468
|
+
await Promise.all([
|
469
|
+
alice.open(),
|
470
|
+
bob.open()
|
471
|
+
]);
|
472
|
+
|
473
|
+
const stream = await bob.callStream('method', createPayload('request'));
|
474
|
+
expect(stream).toBeA(Stream);
|
475
|
+
|
476
|
+
await stream.waitUntilReady();
|
477
|
+
|
478
|
+
expect(await Stream.consume(stream)).toEqual([
|
479
|
+
{ ready: true },
|
480
|
+
{ closed: true }
|
481
|
+
]);
|
482
|
+
});
|
415
483
|
});
|
416
484
|
|
417
485
|
describe('with disabled handshake', () => {
|
@@ -419,7 +487,7 @@ describe('RpcPeer', () => {
|
|
419
487
|
const [alicePort] = createLinkedPorts();
|
420
488
|
|
421
489
|
const alice = new RpcPeer({
|
422
|
-
messageHandler: async msg => (
|
490
|
+
messageHandler: async msg => createPayload(),
|
423
491
|
port: alicePort,
|
424
492
|
noHandshake: true
|
425
493
|
});
|
@@ -434,13 +502,13 @@ describe('RpcPeer', () => {
|
|
434
502
|
messageHandler: async (method, msg) => {
|
435
503
|
expect(method).toEqual('method');
|
436
504
|
expect(msg.value).toEqual(Buffer.from('request'));
|
437
|
-
return
|
505
|
+
return createPayload('response');
|
438
506
|
},
|
439
507
|
port: alicePort,
|
440
508
|
noHandshake: true
|
441
509
|
});
|
442
510
|
const bob = new RpcPeer({
|
443
|
-
messageHandler: async (method, msg) => (
|
511
|
+
messageHandler: async (method, msg) => createPayload(),
|
444
512
|
port: bobPort,
|
445
513
|
noHandshake: true
|
446
514
|
});
|
@@ -448,8 +516,8 @@ describe('RpcPeer', () => {
|
|
448
516
|
await alice.open();
|
449
517
|
await bob.open();
|
450
518
|
|
451
|
-
const response = await bob.call('method',
|
452
|
-
expect(response).toEqual(
|
519
|
+
const response = await bob.call('method', createPayload('request'));
|
520
|
+
expect(response).toEqual(createPayload('response'));
|
453
521
|
});
|
454
522
|
});
|
455
523
|
});
|
package/src/rpc.ts
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
import debug from 'debug';
|
6
6
|
import assert from 'node:assert';
|
7
7
|
|
8
|
-
import {
|
8
|
+
import { synchronized, Trigger } from '@dxos/async';
|
9
9
|
import { Stream } from '@dxos/codec-protobuf';
|
10
10
|
import { StackTrace } from '@dxos/debug';
|
11
11
|
import { exponentialBackoffInterval } from '@dxos/util';
|
@@ -143,7 +143,12 @@ export class RpcPeer {
|
|
143
143
|
if (decoded.request) {
|
144
144
|
if (!this._open) {
|
145
145
|
log('Received request while not open.');
|
146
|
-
await this._sendMessage({
|
146
|
+
await this._sendMessage({
|
147
|
+
response: {
|
148
|
+
id: decoded.request.id,
|
149
|
+
error: encodeError(new RpcClosedError())
|
150
|
+
}
|
151
|
+
});
|
147
152
|
return;
|
148
153
|
}
|
149
154
|
|
@@ -169,16 +174,18 @@ export class RpcPeer {
|
|
169
174
|
return; // Ignore when not open.
|
170
175
|
}
|
171
176
|
|
172
|
-
|
173
|
-
|
174
|
-
|
177
|
+
const responseId = decoded.response.id;
|
178
|
+
|
179
|
+
assert(typeof responseId === 'number');
|
180
|
+
if (!this._outgoingRequests.has(responseId)) {
|
181
|
+
log(`Received response with incorrect id: ${responseId}`);
|
175
182
|
return; // Ignore requests with incorrect id.
|
176
183
|
}
|
177
184
|
|
178
|
-
const item = this._outgoingRequests.get(
|
185
|
+
const item = this._outgoingRequests.get(responseId)!;
|
179
186
|
// Delete the request record if no more responses are expected.
|
180
187
|
if (!item.stream) {
|
181
|
-
this._outgoingRequests.delete(
|
188
|
+
this._outgoingRequests.delete(responseId);
|
182
189
|
}
|
183
190
|
|
184
191
|
log(`Response: ${decoded.response.payload?.type_url}`);
|
@@ -240,20 +247,18 @@ export class RpcPeer {
|
|
240
247
|
// Here we're attaching a dummy handler that will not interfere with error handling to avoid that warning.
|
241
248
|
promise.catch(() => {});
|
242
249
|
|
243
|
-
|
250
|
+
void this._sendMessage({
|
244
251
|
request: {
|
245
252
|
id,
|
246
253
|
method,
|
247
|
-
payload: request
|
254
|
+
payload: request,
|
255
|
+
stream: false
|
248
256
|
}
|
249
257
|
});
|
250
258
|
|
251
|
-
const timeoutPromise = sleep(this._options.timeout ?? DEFAULT_TIMEOUT).then(() => Promise.reject(new Error('Timeout')));
|
252
|
-
timeoutPromise.catch(() => {}); // Mute the promise.
|
253
|
-
|
254
259
|
let response: Response;
|
255
260
|
try {
|
256
|
-
response = await Promise.race([promise,
|
261
|
+
response = await Promise.race([promise, createTimeoutPromise(this._options.timeout ?? DEFAULT_TIMEOUT, new Error(`RPC call timed out: ${method}`))]);
|
257
262
|
} catch (err) {
|
258
263
|
if (err instanceof RpcClosedError) {
|
259
264
|
// Rethrow the error here to have the correct stack-trace.
|
@@ -286,9 +291,11 @@ export class RpcPeer {
|
|
286
291
|
|
287
292
|
const id = this._nextId++;
|
288
293
|
|
289
|
-
return new Stream(({ next, close }) => {
|
294
|
+
return new Stream(({ ready, next, close }) => {
|
290
295
|
const onResponse = (response: Response) => {
|
291
|
-
if (response.
|
296
|
+
if (response.streamReady) {
|
297
|
+
ready();
|
298
|
+
} else if (response.close) {
|
292
299
|
close();
|
293
300
|
} else if (response.error) {
|
294
301
|
assert(response.error.name);
|
@@ -362,6 +369,12 @@ export class RpcPeer {
|
|
362
369
|
assert(req.payload);
|
363
370
|
assert(req.method);
|
364
371
|
const responseStream = this._options.streamHandler(req.method, req.payload);
|
372
|
+
responseStream.onReady(() => {
|
373
|
+
callback({
|
374
|
+
id: req.id,
|
375
|
+
streamReady: true
|
376
|
+
});
|
377
|
+
});
|
365
378
|
responseStream.subscribe(
|
366
379
|
msg => {
|
367
380
|
callback({
|
@@ -410,3 +423,24 @@ const encodeError = (err: any): ErrorResponse => {
|
|
410
423
|
};
|
411
424
|
}
|
412
425
|
};
|
426
|
+
|
427
|
+
/**
|
428
|
+
* Creates a promise that will be rejected after a certain timeout.
|
429
|
+
* The promise will never cause unhandledPromiseRejection.
|
430
|
+
* The timeout will not block the Node.JS process from exiting.
|
431
|
+
*/
|
432
|
+
const createTimeoutPromise = (timeout: number, error: Error) => {
|
433
|
+
const timeoutPromise = new Promise<any>((resolve, reject) => {
|
434
|
+
const timeoutId = setTimeout(
|
435
|
+
() => reject(error),
|
436
|
+
timeout
|
437
|
+
);
|
438
|
+
|
439
|
+
// `unref` prevents the timeout from blocking Node.JS process from exiting. Not available in browsers.
|
440
|
+
if (typeof timeoutId === 'object' && 'unref' in timeoutId) {
|
441
|
+
timeoutId.unref();
|
442
|
+
}
|
443
|
+
});
|
444
|
+
timeoutPromise.catch(() => {}); // Mute the promise.
|
445
|
+
return timeoutPromise;
|
446
|
+
};
|
package/src/service.test.ts
CHANGED
@@ -161,6 +161,7 @@ describe('Protobuf service', () => {
|
|
161
161
|
const stream = client.rpc.testCall({ data: 'requestData' });
|
162
162
|
|
163
163
|
expect(await Stream.consume(stream)).toEqual([
|
164
|
+
{ ready: true },
|
164
165
|
{ data: { data: 'foo' } },
|
165
166
|
{ data: { data: 'bar' } },
|
166
167
|
{ data: { data: 'baz' } },
|
package/src/service.ts
CHANGED
@@ -86,9 +86,12 @@ export const createBundledRpcClient = <S>(descriptors: ServiceBundle<S>, options
|
|
86
86
|
|
87
87
|
const rpc: S = {} as S;
|
88
88
|
for (const serviceName of Object.keys(descriptors) as (keyof S)[]) {
|
89
|
+
// Get full service name with the package name without '.' at the beginning.
|
90
|
+
const serviceFqn = descriptors[serviceName].serviceProto.fullName.slice(1);
|
91
|
+
|
89
92
|
rpc[serviceName] = descriptors[serviceName].createClient({
|
90
|
-
call: (method, req) => peer.call(`${
|
91
|
-
callStream: (method, req) => peer.callStream(`${
|
93
|
+
call: (method, req) => peer.call(`${serviceFqn}.${method}`, req),
|
94
|
+
callStream: (method, req) => peer.callStream(`${serviceFqn}.${method}`, req)
|
92
95
|
});
|
93
96
|
}
|
94
97
|
|
@@ -106,7 +109,10 @@ export interface RpcBundledServerOptions<S> extends Omit<RpcPeerOptions, 'messag
|
|
106
109
|
export const createBundledRpcServer = <S>({ services, handlers, ...rest }: RpcBundledServerOptions<S>): RpcPeer => {
|
107
110
|
const rpc: Record<string, ServiceHandler<any>> = {};
|
108
111
|
for (const serviceName of Object.keys(services) as (keyof S)[]) {
|
109
|
-
|
112
|
+
// Get full service name with the package name without '.' at the beginning.
|
113
|
+
const serviceFqn = services[serviceName].serviceProto.fullName.slice(1);
|
114
|
+
|
115
|
+
rpc[serviceFqn] = services[serviceName].createServer(handlers[serviceName] as any);
|
110
116
|
}
|
111
117
|
|
112
118
|
const peer = new RpcPeer({
|
@@ -133,9 +139,11 @@ export const createBundledRpcServer = <S>({ services, handlers, ...rest }: RpcBu
|
|
133
139
|
};
|
134
140
|
|
135
141
|
const parseMethodName = (method: string): [serviceName: string, methodName: string] => {
|
136
|
-
const
|
137
|
-
|
138
|
-
|
142
|
+
const separator = method.lastIndexOf('.');
|
143
|
+
const serviceName = method.slice(0, separator);
|
144
|
+
const methodName = method.slice(separator + 1);
|
145
|
+
if (serviceName.length === 0 || methodName.length === 0) {
|
146
|
+
throw new Error(`Invalid method: ${method}`);
|
139
147
|
}
|
140
|
-
return [serviceName,
|
148
|
+
return [serviceName, methodName];
|
141
149
|
};
|