@dxos/rpc 2.19.7-dev.42eb65c2 → 2.19.8-dev.98e1d63e
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/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/proto/gen/dxos/rpc.d.ts +13 -2
- package/dist/src/proto/gen/dxos/rpc.d.ts.map +1 -1
- package/dist/src/proto/gen/dxos/rpc.js +9 -0
- package/dist/src/proto/gen/dxos/rpc.js.map +1 -1
- package/dist/src/proto/gen/google/protobuf.d.ts +4 -0
- package/dist/src/proto/gen/google/protobuf.d.ts.map +1 -1
- package/dist/src/proto/gen/index.d.ts +3 -0
- 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 +7 -4
- package/dist/src/rpc.d.ts.map +1 -1
- package/dist/src/rpc.js +2 -0
- package/dist/src/rpc.js.map +1 -1
- package/dist/src/rpc.test.js +42 -42
- package/dist/src/rpc.test.js.map +1 -1
- package/dist/src/trace.d.ts +11 -0
- package/dist/src/trace.d.ts.map +1 -0
- package/dist/src/trace.js +37 -0
- package/dist/src/trace.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/index.ts +1 -0
- package/src/proto/gen/dxos/rpc.ts +12 -2
- package/src/proto/gen/google/protobuf.ts +4 -0
- package/src/proto/gen/index.ts +4 -1
- package/src/proto/import.proto +9 -0
- package/src/rpc.test.ts +46 -45
- package/src/rpc.ts +7 -4
- package/src/trace.ts +42 -0
- package/src/proto/schema.proto +0 -48
package/src/rpc.test.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { sleep } from '@dxos/async';
|
|
|
9
9
|
import { Stream } from '@dxos/codec-protobuf';
|
|
10
10
|
|
|
11
11
|
import { SerializedRpcError } from './errors';
|
|
12
|
+
import { Any } from './proto/gen/google/protobuf';
|
|
12
13
|
import { RpcPeer } from './rpc';
|
|
13
14
|
import { createLinkedPorts } from './testutil';
|
|
14
15
|
|
|
@@ -17,11 +18,11 @@ describe('RpcPeer', () => {
|
|
|
17
18
|
const [alicePort, bobPort] = createLinkedPorts();
|
|
18
19
|
|
|
19
20
|
const alice = new RpcPeer({
|
|
20
|
-
messageHandler: async msg =>
|
|
21
|
+
messageHandler: async msg => ({}),
|
|
21
22
|
port: alicePort
|
|
22
23
|
});
|
|
23
24
|
const bob = new RpcPeer({
|
|
24
|
-
messageHandler: async msg =>
|
|
25
|
+
messageHandler: async msg => ({}),
|
|
25
26
|
port: bobPort
|
|
26
27
|
});
|
|
27
28
|
|
|
@@ -38,13 +39,13 @@ describe('RpcPeer', () => {
|
|
|
38
39
|
const alice = new RpcPeer({
|
|
39
40
|
messageHandler: async (method, msg) => {
|
|
40
41
|
expect(method).toEqual('method');
|
|
41
|
-
expect(msg).toEqual(Buffer.from('request'));
|
|
42
|
-
return Buffer.from('response');
|
|
42
|
+
expect(msg.value).toEqual(Buffer.from('request'));
|
|
43
|
+
return { value: Buffer.from('response') };
|
|
43
44
|
},
|
|
44
45
|
port: alicePort
|
|
45
46
|
});
|
|
46
47
|
const bob = new RpcPeer({
|
|
47
|
-
messageHandler: async (method, msg) =>
|
|
48
|
+
messageHandler: async (method, msg) => ({}),
|
|
48
49
|
port: bobPort
|
|
49
50
|
});
|
|
50
51
|
|
|
@@ -53,8 +54,8 @@ describe('RpcPeer', () => {
|
|
|
53
54
|
bob.open()
|
|
54
55
|
]);
|
|
55
56
|
|
|
56
|
-
const response = await bob.call('method', Buffer.from('request'));
|
|
57
|
-
expect(response).toEqual(Buffer.from('response'));
|
|
57
|
+
const response = await bob.call('method', { value: Buffer.from('request') });
|
|
58
|
+
expect(response).toEqual({ value: Buffer.from('response') });
|
|
58
59
|
});
|
|
59
60
|
|
|
60
61
|
test('can send multiple requests', async () => {
|
|
@@ -65,7 +66,7 @@ describe('RpcPeer', () => {
|
|
|
65
66
|
expect(method).toEqual('method');
|
|
66
67
|
await sleep(5);
|
|
67
68
|
|
|
68
|
-
const text = Buffer.from(msg).toString();
|
|
69
|
+
const text = Buffer.from(msg.value!).toString();
|
|
69
70
|
|
|
70
71
|
if (text === 'error') {
|
|
71
72
|
throw new Error('test error');
|
|
@@ -76,7 +77,7 @@ describe('RpcPeer', () => {
|
|
|
76
77
|
port: alicePort
|
|
77
78
|
});
|
|
78
79
|
const bob = new RpcPeer({
|
|
79
|
-
messageHandler: async msg =>
|
|
80
|
+
messageHandler: async msg => ({}),
|
|
80
81
|
port: bobPort
|
|
81
82
|
});
|
|
82
83
|
|
|
@@ -85,14 +86,14 @@ describe('RpcPeer', () => {
|
|
|
85
86
|
bob.open()
|
|
86
87
|
]);
|
|
87
88
|
|
|
88
|
-
expect(await bob.call('method', Buffer.from('request'))).toEqual(Buffer.from('request'));
|
|
89
|
+
expect((await bob.call('method', { value: Buffer.from('request') })).value).toEqual(Buffer.from('request'));
|
|
89
90
|
|
|
90
|
-
const parallel1 = bob.call('method', Buffer.from('p1'));
|
|
91
|
-
const parallel2 = bob.call('method', Buffer.from('p2'));
|
|
92
|
-
const error = bob.call('method', Buffer.from('error'));
|
|
91
|
+
const parallel1 = bob.call('method', { value: Buffer.from('p1') });
|
|
92
|
+
const parallel2 = bob.call('method', { value: Buffer.from('p2') });
|
|
93
|
+
const error = bob.call('method', { value: Buffer.from('error') });
|
|
93
94
|
|
|
94
|
-
await expect(await parallel1).toEqual(Buffer.from('p1'));
|
|
95
|
-
await expect(await parallel2).toEqual(Buffer.from('p2'));
|
|
95
|
+
await expect(await parallel1).toEqual({ value: Buffer.from('p1') });
|
|
96
|
+
await expect(await parallel2).toEqual({ value: Buffer.from('p2') });
|
|
96
97
|
await expect(error).toBeRejected();
|
|
97
98
|
});
|
|
98
99
|
|
|
@@ -111,7 +112,7 @@ describe('RpcPeer', () => {
|
|
|
111
112
|
port: alicePort
|
|
112
113
|
});
|
|
113
114
|
const bob = new RpcPeer({
|
|
114
|
-
messageHandler: async msg =>
|
|
115
|
+
messageHandler: async msg => ({}),
|
|
115
116
|
port: bobPort
|
|
116
117
|
});
|
|
117
118
|
|
|
@@ -122,7 +123,7 @@ describe('RpcPeer', () => {
|
|
|
122
123
|
|
|
123
124
|
let error!: Error;
|
|
124
125
|
try {
|
|
125
|
-
await bob.call('RpcMethodName', Buffer.from('request'));
|
|
126
|
+
await bob.call('RpcMethodName', { value: Buffer.from('request') });
|
|
126
127
|
} catch (err: any) {
|
|
127
128
|
error = err;
|
|
128
129
|
}
|
|
@@ -145,7 +146,7 @@ describe('RpcPeer', () => {
|
|
|
145
146
|
port: alicePort
|
|
146
147
|
});
|
|
147
148
|
const bob = new RpcPeer({
|
|
148
|
-
messageHandler: async msg =>
|
|
149
|
+
messageHandler: async msg => ({}),
|
|
149
150
|
port: bobPort
|
|
150
151
|
});
|
|
151
152
|
|
|
@@ -154,7 +155,7 @@ describe('RpcPeer', () => {
|
|
|
154
155
|
bob.open()
|
|
155
156
|
]);
|
|
156
157
|
|
|
157
|
-
const req = bob.call('method', Buffer.from('request'));
|
|
158
|
+
const req = bob.call('method', { value: Buffer.from('request') });
|
|
158
159
|
bob.close();
|
|
159
160
|
|
|
160
161
|
await expect(req).toBeRejected();
|
|
@@ -172,7 +173,7 @@ describe('RpcPeer', () => {
|
|
|
172
173
|
port: alicePort
|
|
173
174
|
});
|
|
174
175
|
const bob = new RpcPeer({
|
|
175
|
-
messageHandler: async msg =>
|
|
176
|
+
messageHandler: async msg => ({}),
|
|
176
177
|
port: bobPort,
|
|
177
178
|
timeout: 50
|
|
178
179
|
});
|
|
@@ -183,7 +184,7 @@ describe('RpcPeer', () => {
|
|
|
183
184
|
]);
|
|
184
185
|
|
|
185
186
|
alice.close();
|
|
186
|
-
const req = bob.call('method', Buffer.from('request'));
|
|
187
|
+
const req = bob.call('method', { value: Buffer.from('request') });
|
|
187
188
|
|
|
188
189
|
await expect(req).toBeRejected();
|
|
189
190
|
});
|
|
@@ -191,11 +192,11 @@ describe('RpcPeer', () => {
|
|
|
191
192
|
test('open waits for the other peer to call open', async () => {
|
|
192
193
|
const [alicePort, bobPort] = createLinkedPorts();
|
|
193
194
|
const alice: RpcPeer = new RpcPeer({
|
|
194
|
-
messageHandler: async msg =>
|
|
195
|
+
messageHandler: async msg => ({}),
|
|
195
196
|
port: alicePort
|
|
196
197
|
});
|
|
197
198
|
const bob = new RpcPeer({
|
|
198
|
-
messageHandler: async msg =>
|
|
199
|
+
messageHandler: async msg => ({}),
|
|
199
200
|
port: bobPort
|
|
200
201
|
});
|
|
201
202
|
|
|
@@ -219,7 +220,7 @@ describe('RpcPeer', () => {
|
|
|
219
220
|
|
|
220
221
|
// eslint-disable-next-line prefer-const
|
|
221
222
|
const alice: RpcPeer = new RpcPeer({
|
|
222
|
-
messageHandler: async msg =>
|
|
223
|
+
messageHandler: async msg => ({}),
|
|
223
224
|
port: alicePort
|
|
224
225
|
});
|
|
225
226
|
const aliceOpen = alice.open();
|
|
@@ -227,7 +228,7 @@ describe('RpcPeer', () => {
|
|
|
227
228
|
await sleep(5);
|
|
228
229
|
|
|
229
230
|
const bob = new RpcPeer({
|
|
230
|
-
messageHandler: async msg =>
|
|
231
|
+
messageHandler: async msg => ({}),
|
|
231
232
|
port: bobPort
|
|
232
233
|
});
|
|
233
234
|
|
|
@@ -243,20 +244,20 @@ describe('RpcPeer', () => {
|
|
|
243
244
|
const [alicePort, bobPort] = createLinkedPorts();
|
|
244
245
|
|
|
245
246
|
const alice = new RpcPeer({
|
|
246
|
-
messageHandler: async msg =>
|
|
247
|
+
messageHandler: async msg => ({}),
|
|
247
248
|
streamHandler: (method, msg) => {
|
|
248
249
|
expect(method).toEqual('method');
|
|
249
|
-
expect(msg).toEqual(Buffer.from('request'));
|
|
250
|
-
return new Stream<
|
|
251
|
-
next(Buffer.from('res1'));
|
|
252
|
-
next(Buffer.from('res2'));
|
|
250
|
+
expect(msg.value!).toEqual(Buffer.from('request'));
|
|
251
|
+
return new Stream<Any>(({ next, close }) => {
|
|
252
|
+
next({ value: Buffer.from('res1') });
|
|
253
|
+
next({ value: Buffer.from('res2') });
|
|
253
254
|
close();
|
|
254
255
|
});
|
|
255
256
|
},
|
|
256
257
|
port: alicePort
|
|
257
258
|
});
|
|
258
259
|
const bob = new RpcPeer({
|
|
259
|
-
messageHandler: async msg =>
|
|
260
|
+
messageHandler: async msg => ({}),
|
|
260
261
|
port: bobPort
|
|
261
262
|
});
|
|
262
263
|
|
|
@@ -265,12 +266,12 @@ describe('RpcPeer', () => {
|
|
|
265
266
|
bob.open()
|
|
266
267
|
]);
|
|
267
268
|
|
|
268
|
-
const stream = await bob.callStream('method', Buffer.from('request'));
|
|
269
|
+
const stream = await bob.callStream('method', { value: Buffer.from('request') });
|
|
269
270
|
expect(stream).toBeA(Stream);
|
|
270
271
|
|
|
271
272
|
expect(await Stream.consume(stream)).toEqual([
|
|
272
|
-
{ data: Buffer.from('res1') },
|
|
273
|
-
{ data: Buffer.from('res2') },
|
|
273
|
+
{ data: { value: Buffer.from('res1') } },
|
|
274
|
+
{ data: { value: Buffer.from('res2') } },
|
|
274
275
|
{ closed: true }
|
|
275
276
|
]);
|
|
276
277
|
});
|
|
@@ -279,18 +280,18 @@ describe('RpcPeer', () => {
|
|
|
279
280
|
const [alicePort, bobPort] = createLinkedPorts();
|
|
280
281
|
|
|
281
282
|
const alice = new RpcPeer({
|
|
282
|
-
messageHandler: async msg =>
|
|
283
|
+
messageHandler: async msg => ({}),
|
|
283
284
|
streamHandler: (method, msg) => {
|
|
284
285
|
expect(method).toEqual('method');
|
|
285
|
-
expect(msg).toEqual(Buffer.from('request'));
|
|
286
|
-
return new Stream<
|
|
286
|
+
expect(msg.value).toEqual(Buffer.from('request'));
|
|
287
|
+
return new Stream<Any>(({ next, close }) => {
|
|
287
288
|
close(new Error('Test error'));
|
|
288
289
|
});
|
|
289
290
|
},
|
|
290
291
|
port: alicePort
|
|
291
292
|
});
|
|
292
293
|
const bob = new RpcPeer({
|
|
293
|
-
messageHandler: async msg =>
|
|
294
|
+
messageHandler: async msg => ({}),
|
|
294
295
|
port: bobPort
|
|
295
296
|
});
|
|
296
297
|
|
|
@@ -299,7 +300,7 @@ describe('RpcPeer', () => {
|
|
|
299
300
|
bob.open()
|
|
300
301
|
]);
|
|
301
302
|
|
|
302
|
-
const stream = await bob.callStream('method', Buffer.from('request'));
|
|
303
|
+
const stream = await bob.callStream('method', { value: Buffer.from('request') });
|
|
303
304
|
expect(stream).toBeA(Stream);
|
|
304
305
|
|
|
305
306
|
const msgs = await Stream.consume(stream);
|
|
@@ -315,9 +316,9 @@ describe('RpcPeer', () => {
|
|
|
315
316
|
|
|
316
317
|
let closeCalled = false;
|
|
317
318
|
const alice = new RpcPeer({
|
|
318
|
-
messageHandler: async msg =>
|
|
319
|
+
messageHandler: async msg => ({}),
|
|
319
320
|
streamHandler: (method, msg) => {
|
|
320
|
-
return new Stream<
|
|
321
|
+
return new Stream<Any>(({ next, close }) => {
|
|
321
322
|
return () => {
|
|
322
323
|
closeCalled = true;
|
|
323
324
|
};
|
|
@@ -327,7 +328,7 @@ describe('RpcPeer', () => {
|
|
|
327
328
|
});
|
|
328
329
|
|
|
329
330
|
const bob = new RpcPeer({
|
|
330
|
-
messageHandler: async msg =>
|
|
331
|
+
messageHandler: async msg => ({}),
|
|
331
332
|
port: bobPort
|
|
332
333
|
});
|
|
333
334
|
|
|
@@ -336,7 +337,7 @@ describe('RpcPeer', () => {
|
|
|
336
337
|
bob.open()
|
|
337
338
|
]);
|
|
338
339
|
|
|
339
|
-
const stream = bob.callStream('method', Buffer.from('request'));
|
|
340
|
+
const stream = bob.callStream('method', { value: Buffer.from('request') });
|
|
340
341
|
stream.close();
|
|
341
342
|
|
|
342
343
|
await sleep(1);
|
|
@@ -350,7 +351,7 @@ describe('RpcPeer', () => {
|
|
|
350
351
|
|
|
351
352
|
// eslint-disable-next-line prefer-const
|
|
352
353
|
const alice: RpcPeer = new RpcPeer({
|
|
353
|
-
messageHandler: async msg =>
|
|
354
|
+
messageHandler: async msg => ({}),
|
|
354
355
|
port: alicePort
|
|
355
356
|
});
|
|
356
357
|
const aliceOpen = alice.open();
|
|
@@ -358,7 +359,7 @@ describe('RpcPeer', () => {
|
|
|
358
359
|
await sleep(5);
|
|
359
360
|
|
|
360
361
|
const bob = new RpcPeer({
|
|
361
|
-
messageHandler: async msg =>
|
|
362
|
+
messageHandler: async msg => ({}),
|
|
362
363
|
port: bobPort
|
|
363
364
|
});
|
|
364
365
|
|
package/src/rpc.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { StackTrace } from '@dxos/debug';
|
|
|
12
12
|
import { RpcClosedError, RpcNotOpenError, SerializedRpcError } from './errors';
|
|
13
13
|
import { schema } from './proto/gen';
|
|
14
14
|
import { Request, Response, Error as ErrorResponse, RpcMessage } from './proto/gen/dxos/rpc';
|
|
15
|
+
import { Any } from './proto/gen/google/protobuf';
|
|
15
16
|
|
|
16
17
|
const DEFAULT_TIMEOUT = 3000;
|
|
17
18
|
|
|
@@ -20,8 +21,8 @@ const log = debug('dxos:rpc');
|
|
|
20
21
|
type MaybePromise<T> = Promise<T> | T
|
|
21
22
|
|
|
22
23
|
export interface RpcPeerOptions {
|
|
23
|
-
messageHandler: (method: string, request:
|
|
24
|
-
streamHandler?: (method: string, request:
|
|
24
|
+
messageHandler: (method: string, request: Any) => MaybePromise<Any>
|
|
25
|
+
streamHandler?: (method: string, request: Any) => Stream<Any>
|
|
25
26
|
port: RpcPort,
|
|
26
27
|
timeout?: number,
|
|
27
28
|
}
|
|
@@ -55,6 +56,8 @@ const codec = schema.getCodecForType('dxos.rpc.RpcMessage');
|
|
|
55
56
|
* Both sides must be opened before making any RPC calls.
|
|
56
57
|
*
|
|
57
58
|
* Errors inside the handler get serialized and sent to the other side.
|
|
59
|
+
*
|
|
60
|
+
* Inspired by JSON-RPC 2.0 https://www.jsonrpc.org/specification.
|
|
58
61
|
*/
|
|
59
62
|
export class RpcPeer {
|
|
60
63
|
private readonly _outgoingRequests = new Map<number, RequestItem>();
|
|
@@ -169,7 +172,7 @@ export class RpcPeer {
|
|
|
169
172
|
*
|
|
170
173
|
* Peer should be open before making this call.
|
|
171
174
|
*/
|
|
172
|
-
async call (method: string, request:
|
|
175
|
+
async call (method: string, request: Any): Promise<Any> {
|
|
173
176
|
if (!this._open) {
|
|
174
177
|
throw new RpcNotOpenError();
|
|
175
178
|
}
|
|
@@ -223,7 +226,7 @@ export class RpcPeer {
|
|
|
223
226
|
*
|
|
224
227
|
* Peer should be open before making this call.
|
|
225
228
|
*/
|
|
226
|
-
callStream (method: string, request:
|
|
229
|
+
callStream (method: string, request: Any): Stream<Any> {
|
|
227
230
|
if (!this._open) {
|
|
228
231
|
throw new RpcNotOpenError();
|
|
229
232
|
}
|
package/src/trace.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2021 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Event } from '@dxos/async';
|
|
6
|
+
|
|
7
|
+
import { MessageTrace } from './proto/gen/dxos/rpc';
|
|
8
|
+
import { RpcPort } from './rpc';
|
|
9
|
+
|
|
10
|
+
export class PortTracer {
|
|
11
|
+
readonly message = new Event<MessageTrace>();
|
|
12
|
+
|
|
13
|
+
private readonly _port: RpcPort;
|
|
14
|
+
|
|
15
|
+
constructor (
|
|
16
|
+
private readonly _wrappedPort: RpcPort
|
|
17
|
+
) {
|
|
18
|
+
this._port = {
|
|
19
|
+
send: (msg: Uint8Array) => {
|
|
20
|
+
this.message.emit({
|
|
21
|
+
direction: MessageTrace.Direction.OUTGOING,
|
|
22
|
+
data: msg
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return this._wrappedPort.send(msg);
|
|
26
|
+
},
|
|
27
|
+
subscribe: (cb: (msg: Uint8Array) => void) => {
|
|
28
|
+
return this._wrappedPort.subscribe(msg => {
|
|
29
|
+
this.message.emit({
|
|
30
|
+
direction: MessageTrace.Direction.INCOMING,
|
|
31
|
+
data: msg
|
|
32
|
+
});
|
|
33
|
+
cb(msg);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public get port () {
|
|
40
|
+
return this._port;
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/proto/schema.proto
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2020 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
syntax = "proto3";
|
|
6
|
-
|
|
7
|
-
package dxos.rpc;
|
|
8
|
-
|
|
9
|
-
message RpcMessage {
|
|
10
|
-
oneof content {
|
|
11
|
-
Request request = 1;
|
|
12
|
-
Response response = 2;
|
|
13
|
-
|
|
14
|
-
/// Means that the node is open to receiving requests. Second stage of the hasnshake protocol.
|
|
15
|
-
bool open = 3;
|
|
16
|
-
|
|
17
|
-
StreamClose streamClose = 4;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
message Request {
|
|
22
|
-
int32 id = 1;
|
|
23
|
-
string method = 2;
|
|
24
|
-
bytes payload = 3;
|
|
25
|
-
bool stream = 4;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
message Response {
|
|
29
|
-
int32 id = 1;
|
|
30
|
-
oneof content {
|
|
31
|
-
bytes payload = 2;
|
|
32
|
-
Error error = 3;
|
|
33
|
-
// Sent when stream is closed without an error.
|
|
34
|
-
bool close = 4;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Sent by client to end the streaming response.
|
|
39
|
-
message StreamClose {
|
|
40
|
-
int32 id = 1;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
message Error {
|
|
45
|
-
string name = 1;
|
|
46
|
-
string message = 2;
|
|
47
|
-
string stack = 3;
|
|
48
|
-
}
|