@dxos/rpc 2.33.9-dev.7d11f506 → 2.33.9-dev.9bbef4e2
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 +55 -38
- 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 +10 -5
- 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 +47 -27
- 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
@@ -2,12 +2,13 @@
|
|
2
2
|
// Copyright 2021 DXOS.org
|
3
3
|
//
|
4
4
|
|
5
|
-
import assert from 'assert';
|
6
5
|
import debug from 'debug';
|
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
|
+
import { exponentialBackoffInterval } from '@dxos/util';
|
11
12
|
|
12
13
|
import { RpcClosedError, RpcNotOpenError, SerializedRpcError } from './errors';
|
13
14
|
import { schema } from './proto/gen';
|
@@ -142,7 +143,12 @@ export class RpcPeer {
|
|
142
143
|
if (decoded.request) {
|
143
144
|
if (!this._open) {
|
144
145
|
log('Received request while not open.');
|
145
|
-
await this._sendMessage({
|
146
|
+
await this._sendMessage({
|
147
|
+
response: {
|
148
|
+
id: decoded.request.id,
|
149
|
+
error: encodeError(new RpcClosedError())
|
150
|
+
}
|
151
|
+
});
|
146
152
|
return;
|
147
153
|
}
|
148
154
|
|
@@ -168,16 +174,18 @@ export class RpcPeer {
|
|
168
174
|
return; // Ignore when not open.
|
169
175
|
}
|
170
176
|
|
171
|
-
|
172
|
-
|
173
|
-
|
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}`);
|
174
182
|
return; // Ignore requests with incorrect id.
|
175
183
|
}
|
176
184
|
|
177
|
-
const item = this._outgoingRequests.get(
|
185
|
+
const item = this._outgoingRequests.get(responseId)!;
|
178
186
|
// Delete the request record if no more responses are expected.
|
179
187
|
if (!item.stream) {
|
180
|
-
this._outgoingRequests.delete(
|
188
|
+
this._outgoingRequests.delete(responseId);
|
181
189
|
}
|
182
190
|
|
183
191
|
log(`Response: ${decoded.response.payload?.type_url}`);
|
@@ -239,20 +247,18 @@ export class RpcPeer {
|
|
239
247
|
// Here we're attaching a dummy handler that will not interfere with error handling to avoid that warning.
|
240
248
|
promise.catch(() => {});
|
241
249
|
|
242
|
-
|
250
|
+
void this._sendMessage({
|
243
251
|
request: {
|
244
252
|
id,
|
245
253
|
method,
|
246
|
-
payload: request
|
254
|
+
payload: request,
|
255
|
+
stream: false
|
247
256
|
}
|
248
257
|
});
|
249
258
|
|
250
|
-
const timeoutPromise = sleep(this._options.timeout ?? DEFAULT_TIMEOUT).then(() => Promise.reject(new Error('Timeout')));
|
251
|
-
timeoutPromise.catch(() => {}); // Mute the promise.
|
252
|
-
|
253
259
|
let response: Response;
|
254
260
|
try {
|
255
|
-
response = await Promise.race([promise,
|
261
|
+
response = await Promise.race([promise, createTimeoutPromise(this._options.timeout ?? DEFAULT_TIMEOUT, new Error(`RPC call timed out: ${method}`))]);
|
256
262
|
} catch (err) {
|
257
263
|
if (err instanceof RpcClosedError) {
|
258
264
|
// Rethrow the error here to have the correct stack-trace.
|
@@ -285,9 +291,11 @@ export class RpcPeer {
|
|
285
291
|
|
286
292
|
const id = this._nextId++;
|
287
293
|
|
288
|
-
return new Stream(({ next, close }) => {
|
294
|
+
return new Stream(({ ready, next, close }) => {
|
289
295
|
const onResponse = (response: Response) => {
|
290
|
-
if (response.
|
296
|
+
if (response.streamReady) {
|
297
|
+
ready();
|
298
|
+
} else if (response.close) {
|
291
299
|
close();
|
292
300
|
} else if (response.error) {
|
293
301
|
assert(response.error.name);
|
@@ -361,6 +369,12 @@ export class RpcPeer {
|
|
361
369
|
assert(req.payload);
|
362
370
|
assert(req.method);
|
363
371
|
const responseStream = this._options.streamHandler(req.method, req.payload);
|
372
|
+
responseStream.onReady(() => {
|
373
|
+
callback({
|
374
|
+
id: req.id,
|
375
|
+
streamReady: true
|
376
|
+
});
|
377
|
+
});
|
364
378
|
responseStream.subscribe(
|
365
379
|
msg => {
|
366
380
|
callback({
|
@@ -411,16 +425,22 @@ const encodeError = (err: any): ErrorResponse => {
|
|
411
425
|
};
|
412
426
|
|
413
427
|
/**
|
414
|
-
*
|
415
|
-
*
|
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.
|
416
431
|
*/
|
417
|
-
const
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
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;
|
426
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
|
};
|