starpc 0.3.5 → 0.4.1
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/Makefile +22 -13
- package/README.md +4 -0
- package/dist/echo/client-test.js +1 -1
- package/dist/echo/{echo.d.ts → echo.pb.d.ts} +0 -0
- package/dist/echo/{echo.js → echo.pb.js} +0 -1
- package/dist/echo/index.d.ts +1 -1
- package/dist/echo/index.js +1 -1
- package/dist/echo/server.d.ts +1 -1
- package/dist/rpcstream/rpcstream.d.ts +19 -0
- package/dist/rpcstream/rpcstream.js +94 -0
- package/dist/rpcstream/rpcstream.pb.d.ts +85 -0
- package/dist/rpcstream/rpcstream.pb.js +160 -0
- package/dist/srpc/broadcast-channel.js +0 -10
- package/dist/srpc/client-rpc.d.ts +1 -1
- package/dist/srpc/client.d.ts +5 -5
- package/dist/srpc/client.js +21 -25
- package/dist/srpc/common-rpc.d.ts +2 -2
- package/dist/srpc/common-rpc.js +1 -15
- package/dist/srpc/conn-duplex.js +1 -3
- package/dist/srpc/conn.d.ts +1 -1
- package/dist/srpc/conn.js +0 -4
- package/dist/srpc/handler.js +12 -14
- package/dist/srpc/index.d.ts +2 -1
- package/dist/srpc/index.js +1 -0
- package/dist/srpc/message-port.js +0 -10
- package/dist/srpc/mux.js +4 -2
- package/dist/srpc/observable-source.d.ts +9 -0
- package/dist/srpc/observable-source.js +25 -0
- package/dist/srpc/packet.d.ts +1 -1
- package/dist/srpc/packet.js +1 -1
- package/dist/srpc/{rpcproto.d.ts → rpcproto.pb.d.ts} +0 -0
- package/dist/srpc/{rpcproto.js → rpcproto.pb.js} +0 -0
- package/dist/srpc/server-rpc.d.ts +1 -1
- package/dist/srpc/server-rpc.js +0 -2
- package/dist/srpc/server.d.ts +4 -4
- package/dist/srpc/server.js +6 -7
- package/dist/srpc/stream.d.ts +1 -1
- package/dist/srpc/websocket.js +1 -3
- package/e2e/debug.test +0 -0
- package/e2e/e2e_test.go +20 -2
- package/echo/client-test.ts +1 -1
- package/echo/{echo.ts → echo.pb.ts} +0 -0
- package/echo/index.ts +1 -1
- package/echo/server.ts +1 -1
- package/go.mod +2 -2
- package/go.sum +2 -2
- package/integration/integration.ts +2 -2
- package/package.json +4 -3
- package/srpc/broadcast-channel.ts +1 -1
- package/srpc/client-rpc.go +8 -3
- package/srpc/client-rpc.ts +1 -1
- package/srpc/client.go +4 -4
- package/srpc/client.ts +27 -25
- package/srpc/common-rpc.ts +2 -2
- package/srpc/conn-duplex.ts +1 -1
- package/srpc/conn.ts +1 -1
- package/srpc/handler.ts +14 -10
- package/srpc/index.ts +2 -2
- package/srpc/{rpc-stream.go → msg-stream.go} +13 -13
- package/srpc/muxed-conn.go +31 -0
- package/srpc/observable-source.ts +40 -0
- package/srpc/packet.go +4 -3
- package/srpc/packet.ts +1 -1
- package/srpc/{rpcproto.ts → rpcproto.pb.ts} +0 -0
- package/srpc/server-pipe.go +1 -1
- package/srpc/server-rpc.go +3 -3
- package/srpc/server-rpc.ts +1 -1
- package/srpc/server.go +8 -1
- package/srpc/server.ts +8 -7
- package/srpc/stream.ts +1 -1
- package/srpc/websocket.go +1 -4
- package/srpc/websocket.ts +1 -1
- package/srpc/conn.go +0 -7
package/dist/srpc/common-rpc.js
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
1
|
import { pushable } from 'it-pushable';
|
|
2
|
-
import { Packet } from './rpcproto.js';
|
|
2
|
+
import { Packet } from './rpcproto.pb.js';
|
|
3
3
|
// CommonRPC is common logic between server and client RPCs.
|
|
4
4
|
export class CommonRPC {
|
|
5
|
-
// sink is the data sink for incoming messages.
|
|
6
|
-
sink;
|
|
7
|
-
// source is the packet source for outgoing Packets.
|
|
8
|
-
source;
|
|
9
|
-
// _source is used to write to the source.
|
|
10
|
-
_source;
|
|
11
|
-
// rpcDataSource emits incoming client RPC messages to the caller.
|
|
12
|
-
rpcDataSource;
|
|
13
|
-
// _rpcDataSource is used to write to the rpc message source.
|
|
14
|
-
_rpcDataSource;
|
|
15
|
-
// service is the rpc service
|
|
16
|
-
service;
|
|
17
|
-
// method is the rpc method
|
|
18
|
-
method;
|
|
19
5
|
constructor() {
|
|
20
6
|
this.sink = this._createSink();
|
|
21
7
|
const sourcev = this._createSource();
|
package/dist/srpc/conn-duplex.js
CHANGED
|
@@ -4,12 +4,10 @@ import { Conn } from './conn.js';
|
|
|
4
4
|
//
|
|
5
5
|
// expects Uint8Array objects
|
|
6
6
|
export class DuplexConn extends Conn {
|
|
7
|
-
// channel is the iterable
|
|
8
|
-
channel;
|
|
9
7
|
constructor(duplex, server, connParams) {
|
|
10
8
|
super(server, connParams);
|
|
11
9
|
this.channel = duplex;
|
|
12
|
-
pipe(this, this
|
|
10
|
+
pipe(this.channel, this, this.channel);
|
|
13
11
|
}
|
|
14
12
|
// getChannelDuplex returns the Duplex channel.
|
|
15
13
|
getChannelDuplex() {
|
package/dist/srpc/conn.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface ConnParams {
|
|
|
7
7
|
muxerFactory?: StreamMuxerFactory;
|
|
8
8
|
}
|
|
9
9
|
export interface StreamHandler {
|
|
10
|
-
handleStream(strm: Duplex<Uint8Array>):
|
|
10
|
+
handleStream(strm: Duplex<Uint8Array>): void;
|
|
11
11
|
}
|
|
12
12
|
export declare class Conn implements Duplex<Uint8Array> {
|
|
13
13
|
private muxer;
|
package/dist/srpc/conn.js
CHANGED
|
@@ -5,10 +5,6 @@ import { Client } from './client.js';
|
|
|
5
5
|
// Implements the server by handling incoming streams.
|
|
6
6
|
// If the server is unset, rejects any incoming streams.
|
|
7
7
|
export class Conn {
|
|
8
|
-
// muxer is the mplex stream muxer.
|
|
9
|
-
muxer;
|
|
10
|
-
// server is the server side, if set.
|
|
11
|
-
server;
|
|
12
8
|
constructor(server, connParams) {
|
|
13
9
|
if (server) {
|
|
14
10
|
this.server = server;
|
package/dist/srpc/handler.js
CHANGED
|
@@ -4,10 +4,6 @@ import { from as observableFrom } from 'rxjs';
|
|
|
4
4
|
import { buildDecodeMessageTransform, buildEncodeMessageTransform, } from './message.js';
|
|
5
5
|
// StaticHandler is a handler with a definition and implementation.
|
|
6
6
|
export class StaticHandler {
|
|
7
|
-
// service is the service id
|
|
8
|
-
service;
|
|
9
|
-
// methods is the map of method to invoke fn
|
|
10
|
-
methods;
|
|
11
7
|
constructor(serviceID, methods) {
|
|
12
8
|
this.service = serviceID;
|
|
13
9
|
this.methods = methods;
|
|
@@ -38,23 +34,27 @@ export function createInvokeFn(methodInfo, methodProto) {
|
|
|
38
34
|
objectMode: true,
|
|
39
35
|
});
|
|
40
36
|
// pipe responseSink to dataSink.
|
|
41
|
-
|
|
37
|
+
pipe(responseSink, buildEncodeMessageTransform(methodInfo.responseType), dataSink);
|
|
38
|
+
// requestSource is a Source of decoded request messages.
|
|
39
|
+
const requestSource = pipe(dataSource, requestDecode);
|
|
42
40
|
// build the request argument.
|
|
43
41
|
let requestArg;
|
|
44
42
|
if (methodInfo.requestStream) {
|
|
45
|
-
// requestSource is a Source of decoded request messages.
|
|
46
|
-
const requestSource = pipe(dataSource, requestDecode);
|
|
47
43
|
// convert the request data source into an Observable<T>
|
|
48
44
|
requestArg = observableFrom(requestSource);
|
|
49
45
|
}
|
|
50
46
|
else {
|
|
51
47
|
// receive a single message for the argument.
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
for await (const msg of requestSource) {
|
|
49
|
+
if (msg) {
|
|
50
|
+
requestArg = msg;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
56
53
|
}
|
|
57
54
|
}
|
|
55
|
+
if (!requestArg) {
|
|
56
|
+
throw new Error('request object was empty');
|
|
57
|
+
}
|
|
58
58
|
// Call the implementation.
|
|
59
59
|
try {
|
|
60
60
|
const responseObj = methodProto(requestArg);
|
|
@@ -77,9 +77,7 @@ export function createInvokeFn(methodInfo, methodProto) {
|
|
|
77
77
|
},
|
|
78
78
|
complete: () => {
|
|
79
79
|
responseSink.end();
|
|
80
|
-
|
|
81
|
-
resolve();
|
|
82
|
-
});
|
|
80
|
+
resolve();
|
|
83
81
|
},
|
|
84
82
|
});
|
|
85
83
|
});
|
package/dist/srpc/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { OpenStreamFunc } from './stream.js';
|
|
1
|
+
export type { PacketHandler, Stream, OpenStreamFunc } from './stream.js';
|
|
2
2
|
export { Client } from './client.js';
|
|
3
3
|
export { Server } from './server.js';
|
|
4
4
|
export { Conn, ConnParams } from './conn.js';
|
|
@@ -6,3 +6,4 @@ export { Handler, InvokeFn, createHandler, createInvokeFn } from './handler.js';
|
|
|
6
6
|
export { Mux, createMux } from './mux.js';
|
|
7
7
|
export { BroadcastChannelIterable, newBroadcastChannelIterable, BroadcastChannelConn, } from './broadcast-channel.js';
|
|
8
8
|
export { MessagePortIterable, newMessagePortIterable, MessagePortConn, } from './message-port.js';
|
|
9
|
+
export { ObservableSource } from './observable-source.js';
|
package/dist/srpc/index.js
CHANGED
|
@@ -5,3 +5,4 @@ export { createHandler, createInvokeFn } from './handler.js';
|
|
|
5
5
|
export { createMux } from './mux.js';
|
|
6
6
|
export { BroadcastChannelIterable, newBroadcastChannelIterable, BroadcastChannelConn, } from './broadcast-channel.js';
|
|
7
7
|
export { MessagePortIterable, newMessagePortIterable, MessagePortConn, } from './message-port.js';
|
|
8
|
+
export { ObservableSource } from './observable-source.js';
|
|
@@ -2,14 +2,6 @@ import { EventIterator } from 'event-iterator';
|
|
|
2
2
|
import { DuplexConn } from './conn-duplex.js';
|
|
3
3
|
// MessagePortIterable is a AsyncIterable wrapper for MessagePort.
|
|
4
4
|
export class MessagePortIterable {
|
|
5
|
-
// port is the message port
|
|
6
|
-
port;
|
|
7
|
-
// sink is the sink for incoming messages.
|
|
8
|
-
sink;
|
|
9
|
-
// source is the source for outgoing messages.
|
|
10
|
-
source;
|
|
11
|
-
// _source is the EventIterator for source.
|
|
12
|
-
_source;
|
|
13
5
|
constructor(port) {
|
|
14
6
|
this.port = port;
|
|
15
7
|
this.sink = this._createSink();
|
|
@@ -51,8 +43,6 @@ export function newMessagePortIterable(port) {
|
|
|
51
43
|
//
|
|
52
44
|
// expects Uint8Array objects over the MessagePort.
|
|
53
45
|
export class MessagePortConn extends DuplexConn {
|
|
54
|
-
// messagePort is the message port iterable.
|
|
55
|
-
messagePort;
|
|
56
46
|
constructor(port, server, connParams) {
|
|
57
47
|
const messagePort = new MessagePortIterable(port);
|
|
58
48
|
super(messagePort, server, connParams);
|
package/dist/srpc/mux.js
CHANGED
|
@@ -5,8 +5,10 @@ export function createMux() {
|
|
|
5
5
|
// StaticMux contains a in-memory mapping between service ID and handlers.
|
|
6
6
|
// implements Mux
|
|
7
7
|
export class StaticMux {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
constructor() {
|
|
9
|
+
// services contains a mapping from service id to handlers.
|
|
10
|
+
this.services = {};
|
|
11
|
+
}
|
|
10
12
|
register(handler) {
|
|
11
13
|
const serviceID = handler?.getServiceID();
|
|
12
14
|
if (!serviceID) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Source } from 'it-stream-types';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
export declare class ObservableSource<T> {
|
|
4
|
+
readonly source: Source<T>;
|
|
5
|
+
private readonly _source;
|
|
6
|
+
private readonly subscription;
|
|
7
|
+
constructor(observable: Observable<T>);
|
|
8
|
+
close(err?: Error): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { pushable } from 'it-pushable';
|
|
2
|
+
// ObservableSource wraps an Observable into a Source.
|
|
3
|
+
export class ObservableSource {
|
|
4
|
+
constructor(observable) {
|
|
5
|
+
const source = pushable({ objectMode: true });
|
|
6
|
+
this.source = source;
|
|
7
|
+
this._source = source;
|
|
8
|
+
this.subscription = observable.subscribe({
|
|
9
|
+
next: (value) => {
|
|
10
|
+
this._source.push(value);
|
|
11
|
+
},
|
|
12
|
+
error: (err) => {
|
|
13
|
+
this._source.end(err);
|
|
14
|
+
},
|
|
15
|
+
complete: () => {
|
|
16
|
+
this._source.end();
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// close closes the subscription.
|
|
21
|
+
close(err) {
|
|
22
|
+
this._source.end(err);
|
|
23
|
+
this.subscription.unsubscribe();
|
|
24
|
+
}
|
|
25
|
+
}
|
package/dist/srpc/packet.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Transform } from 'it-stream-types';
|
|
2
|
-
import { Packet } from './rpcproto.js';
|
|
2
|
+
import { Packet } from './rpcproto.pb.js';
|
|
3
3
|
export declare const decodePacketSource: (source: import("it-stream-types").Source<Uint8Array | Uint8Array[]>) => AsyncIterable<Packet>;
|
|
4
4
|
export declare const encodePacketSource: (source: import("it-stream-types").Source<Packet | Packet[]>) => AsyncIterable<Uint8Array>;
|
|
5
5
|
export declare function prependLengthPrefixTransform(): Transform<Uint8Array>;
|
package/dist/srpc/packet.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { encode as lengthPrefixEncode, decode as lengthPrefixDecode, } from 'it-length-prefixed';
|
|
2
|
-
import { Packet } from './rpcproto.js';
|
|
2
|
+
import { Packet } from './rpcproto.pb.js';
|
|
3
3
|
import { buildDecodeMessageTransform, buildEncodeMessageTransform, } from './message.js';
|
|
4
4
|
// decodePacketSource decodes packets from a binary data stream.
|
|
5
5
|
export const decodePacketSource = buildDecodeMessageTransform(Packet);
|
|
File without changes
|
|
File without changes
|
package/dist/srpc/server-rpc.js
CHANGED
package/dist/srpc/server.d.ts
CHANGED
|
@@ -2,13 +2,13 @@ import { Stream } from '@libp2p/interface-connection';
|
|
|
2
2
|
import { Duplex } from 'it-stream-types';
|
|
3
3
|
import { Mux } from './mux.js';
|
|
4
4
|
import { ServerRPC } from './server-rpc.js';
|
|
5
|
-
import { Packet } from './rpcproto.js';
|
|
5
|
+
import { Packet } from './rpcproto.pb.js';
|
|
6
6
|
import { StreamHandler } from './conn.js';
|
|
7
7
|
export declare class Server implements StreamHandler {
|
|
8
8
|
private mux;
|
|
9
9
|
constructor(mux: Mux);
|
|
10
10
|
startRpc(): ServerRPC;
|
|
11
|
-
handleStream(stream: Stream):
|
|
12
|
-
handleDuplex(stream: Duplex<Uint8Array>):
|
|
13
|
-
handlePacketStream(stream: Duplex<Packet>):
|
|
11
|
+
handleStream(stream: Stream): ServerRPC;
|
|
12
|
+
handleDuplex(stream: Duplex<Uint8Array>): ServerRPC;
|
|
13
|
+
handlePacketStream(stream: Duplex<Packet>): ServerRPC;
|
|
14
14
|
}
|
package/dist/srpc/server.js
CHANGED
|
@@ -3,8 +3,6 @@ import { ServerRPC } from './server-rpc.js';
|
|
|
3
3
|
import { parseLengthPrefixTransform, prependLengthPrefixTransform, decodePacketSource, encodePacketSource, } from './packet.js';
|
|
4
4
|
// Server implements the SRPC server in TypeScript with a Mux.
|
|
5
5
|
export class Server {
|
|
6
|
-
// mux is the mux used to handle requests.
|
|
7
|
-
mux;
|
|
8
6
|
constructor(mux) {
|
|
9
7
|
this.mux = mux;
|
|
10
8
|
}
|
|
@@ -14,18 +12,19 @@ export class Server {
|
|
|
14
12
|
return new ServerRPC(this.mux);
|
|
15
13
|
}
|
|
16
14
|
// handleStream handles an incoming Uint8Array message duplex.
|
|
17
|
-
// closes the stream when the rpc completes.
|
|
18
15
|
handleStream(stream) {
|
|
19
16
|
return this.handleDuplex(stream);
|
|
20
17
|
}
|
|
21
18
|
// handleDuplex handles an incoming message duplex.
|
|
22
|
-
|
|
19
|
+
handleDuplex(stream) {
|
|
23
20
|
const rpc = this.startRpc();
|
|
24
|
-
|
|
21
|
+
pipe(stream, parseLengthPrefixTransform(), decodePacketSource, rpc, encodePacketSource, prependLengthPrefixTransform(), stream);
|
|
22
|
+
return rpc;
|
|
25
23
|
}
|
|
26
24
|
// handlePacketStream handles an incoming Packet duplex.
|
|
27
|
-
|
|
25
|
+
handlePacketStream(stream) {
|
|
28
26
|
const rpc = this.startRpc();
|
|
29
|
-
|
|
27
|
+
pipe(stream, rpc, stream);
|
|
28
|
+
return rpc;
|
|
30
29
|
}
|
|
31
30
|
}
|
package/dist/srpc/stream.d.ts
CHANGED
package/dist/srpc/websocket.js
CHANGED
|
@@ -4,15 +4,13 @@ import { Mplex } from '@libp2p/mplex';
|
|
|
4
4
|
import { Conn } from './conn.js';
|
|
5
5
|
// WebSocketConn implements a connection with a WebSocket and optional Server.
|
|
6
6
|
export class WebSocketConn extends Conn {
|
|
7
|
-
// socket is the web socket
|
|
8
|
-
socket;
|
|
9
7
|
constructor(socket, server) {
|
|
10
8
|
super(server, {
|
|
11
9
|
muxerFactory: new Mplex(),
|
|
12
10
|
});
|
|
13
11
|
this.socket = socket;
|
|
14
12
|
const socketDuplex = duplex(socket);
|
|
15
|
-
pipe(this
|
|
13
|
+
pipe(socketDuplex, this, socketDuplex);
|
|
16
14
|
}
|
|
17
15
|
// getSocket returns the websocket.
|
|
18
16
|
getSocket() {
|
package/e2e/debug.test
ADDED
|
Binary file
|
package/e2e/e2e_test.go
CHANGED
|
@@ -3,10 +3,13 @@ package e2e
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
5
|
"io"
|
|
6
|
+
"net"
|
|
6
7
|
"testing"
|
|
7
8
|
|
|
8
9
|
"github.com/aperturerobotics/starpc/echo"
|
|
9
10
|
"github.com/aperturerobotics/starpc/srpc"
|
|
11
|
+
"github.com/libp2p/go-libp2p/p2p/muxer/mplex"
|
|
12
|
+
mp "github.com/libp2p/go-mplex"
|
|
10
13
|
"github.com/pkg/errors"
|
|
11
14
|
)
|
|
12
15
|
|
|
@@ -20,9 +23,24 @@ func RunE2E(t *testing.T, cb func(client echo.SRPCEchoerClient) error) {
|
|
|
20
23
|
}
|
|
21
24
|
server := srpc.NewServer(mux)
|
|
22
25
|
|
|
26
|
+
// note: also possible to do without mplex:
|
|
27
|
+
// openStream := srpc.NewServerPipe(server)
|
|
28
|
+
// client := srpc.NewClient(openStream)
|
|
29
|
+
|
|
23
30
|
// construct the client
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
clientPipe, serverPipe := net.Pipe()
|
|
32
|
+
|
|
33
|
+
ctx := context.Background()
|
|
34
|
+
go func() {
|
|
35
|
+
serverMp, _ := mp.NewMultiplex(serverPipe, false, nil)
|
|
36
|
+
_ = server.AcceptMuxedConn(ctx, mplex.NewMuxedConn(serverMp))
|
|
37
|
+
}()
|
|
38
|
+
|
|
39
|
+
clientMp, err := mp.NewMultiplex(clientPipe, true, nil)
|
|
40
|
+
if err != nil {
|
|
41
|
+
t.Fatal(err.Error())
|
|
42
|
+
}
|
|
43
|
+
client := srpc.NewClientWithMuxedConn(mplex.NewMuxedConn(clientMp))
|
|
26
44
|
|
|
27
45
|
// construct the client rpc interface
|
|
28
46
|
clientEcho := echo.NewSRPCEchoerClient(client)
|
package/echo/client-test.ts
CHANGED
|
File without changes
|
package/echo/index.ts
CHANGED
package/echo/server.ts
CHANGED
package/go.mod
CHANGED
|
@@ -9,8 +9,9 @@ require (
|
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
require (
|
|
12
|
-
github.com/libp2p/go-libp2p v0.20.1
|
|
12
|
+
github.com/libp2p/go-libp2p v0.20.1-0.20220622205512-3cf611ad8c9c
|
|
13
13
|
github.com/libp2p/go-libp2p-core v0.16.1
|
|
14
|
+
github.com/libp2p/go-mplex v0.7.0
|
|
14
15
|
github.com/sirupsen/logrus v1.8.2-0.20220112234510-85981c045988
|
|
15
16
|
)
|
|
16
17
|
|
|
@@ -25,7 +26,6 @@ require (
|
|
|
25
26
|
github.com/klauspost/compress v1.15.1 // indirect
|
|
26
27
|
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
|
27
28
|
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
|
28
|
-
github.com/libp2p/go-mplex v0.7.0 // indirect
|
|
29
29
|
github.com/libp2p/go-openssl v0.0.7 // indirect
|
|
30
30
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
|
31
31
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect
|
package/go.sum
CHANGED
|
@@ -65,8 +65,8 @@ github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
|
|
65
65
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
|
66
66
|
github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs=
|
|
67
67
|
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
|
|
68
|
-
github.com/libp2p/go-libp2p v0.20.1 h1:
|
|
69
|
-
github.com/libp2p/go-libp2p v0.20.1/go.mod h1:
|
|
68
|
+
github.com/libp2p/go-libp2p v0.20.1-0.20220622205512-3cf611ad8c9c h1:BTR12zXVGQtdk9bT5GLOmdzJrhyFO6YUH3/e8lnkjQ0=
|
|
69
|
+
github.com/libp2p/go-libp2p v0.20.1-0.20220622205512-3cf611ad8c9c/go.mod h1:tqyre7jPbLfhzjQfpiFX6x7wj/sqt1074riPM0Xn/qI=
|
|
70
70
|
github.com/libp2p/go-libp2p-core v0.16.1 h1:bWoiEBqVkpJ13hbv/f69tHODp86t6mvc4fBN4DkK73M=
|
|
71
71
|
github.com/libp2p/go-libp2p-core v0.16.1/go.mod h1:O3i/7y+LqUb0N+qhzXjBjjpchgptWAVMG1Voegk7b4c=
|
|
72
72
|
github.com/libp2p/go-libp2p-testing v0.9.2 h1:dCpODRtRaDZKF8HXT9qqqgON+OMEB423Knrgeod8j84=
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { WebSocketConn } from '../srpc/websocket'
|
|
2
|
-
import { runClientTest } from '../echo'
|
|
1
|
+
import { WebSocketConn } from '../srpc/websocket.js'
|
|
2
|
+
import { runClientTest } from '../echo/client-test.js'
|
|
3
3
|
import WebSocket from 'isomorphic-ws'
|
|
4
4
|
|
|
5
5
|
async function runRPC() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "starpc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Streaming protobuf RPC service protocol over any two-way channel.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"Makefile",
|
|
23
23
|
"dist/echo",
|
|
24
24
|
"dist/srpc",
|
|
25
|
+
"dist/rpcstream",
|
|
25
26
|
"e2e",
|
|
26
27
|
"echo",
|
|
27
28
|
"go.mod",
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
"deps": "depcheck",
|
|
40
41
|
"codegen": "npm run gen",
|
|
41
42
|
"ci": "npm run build && npm run lint:js && npm run lint:go",
|
|
42
|
-
"format": "prettier --write './{srpc,echo,e2e,integration}/**/(*.ts|*.tsx|*.html|*.css)'",
|
|
43
|
+
"format": "prettier --write './{srpc,echo,e2e,integration,rpcstream}/**/(*.ts|*.tsx|*.html|*.css)'",
|
|
43
44
|
"gen": "make genproto",
|
|
44
45
|
"test": "npm run test:js && npm run test:go",
|
|
45
46
|
"test:go": "make test",
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
"integration": "npm run test:integration",
|
|
49
50
|
"lint": "npm run lint:go && npm run lint:js",
|
|
50
51
|
"lint:go": "make lint",
|
|
51
|
-
"lint:js": "eslint -c .eslintrc.js --ext .ts ./{srpc,echo}/**/*.ts",
|
|
52
|
+
"lint:js": "eslint -c .eslintrc.js --ext .ts ./{srpc,echo,rpcstream}/**/*.ts",
|
|
52
53
|
"prepare": "patch-package",
|
|
53
54
|
"precommit": "npm run format"
|
|
54
55
|
},
|
|
@@ -46,8 +46,8 @@ export class BroadcastChannelIterable<T> implements Duplex<T> {
|
|
|
46
46
|
queue.push(ev.data)
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
this.readChannel.addEventListener('message', messageListener)
|
|
50
49
|
|
|
50
|
+
this.readChannel.addEventListener('message', messageListener)
|
|
51
51
|
return () => {
|
|
52
52
|
this.readChannel.removeEventListener('message', messageListener)
|
|
53
53
|
}
|
package/srpc/client-rpc.go
CHANGED
|
@@ -46,9 +46,8 @@ func NewClientRPC(ctx context.Context, service, method string) *ClientRPC {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// Start sets the writer and writes the MsgSend message.
|
|
49
|
-
// firstMsg can be nil, but is usually set if this is a non-streaming rpc.
|
|
50
49
|
// must only be called once!
|
|
51
|
-
func (r *ClientRPC) Start(writer Writer, firstMsg []byte) error {
|
|
50
|
+
func (r *ClientRPC) Start(writer Writer, writeFirstMsg bool, firstMsg []byte) error {
|
|
52
51
|
select {
|
|
53
52
|
case <-r.ctx.Done():
|
|
54
53
|
r.Close()
|
|
@@ -56,7 +55,13 @@ func (r *ClientRPC) Start(writer Writer, firstMsg []byte) error {
|
|
|
56
55
|
default:
|
|
57
56
|
}
|
|
58
57
|
r.writer = writer
|
|
59
|
-
|
|
58
|
+
var firstMsgEmpty bool
|
|
59
|
+
if writeFirstMsg {
|
|
60
|
+
firstMsgEmpty = len(firstMsg) == 0
|
|
61
|
+
} else {
|
|
62
|
+
firstMsg = nil
|
|
63
|
+
}
|
|
64
|
+
pkt := NewCallStartPacket(r.service, r.method, firstMsg, firstMsgEmpty)
|
|
60
65
|
if err := writer.WritePacket(pkt); err != nil {
|
|
61
66
|
r.Close()
|
|
62
67
|
return err
|
package/srpc/client-rpc.ts
CHANGED
package/srpc/client.go
CHANGED
|
@@ -19,7 +19,7 @@ type Client interface {
|
|
|
19
19
|
|
|
20
20
|
// OpenStreamFunc opens a stream with a remote.
|
|
21
21
|
// msgHandler must not be called concurrently.
|
|
22
|
-
type OpenStreamFunc = func(ctx context.Context, msgHandler
|
|
22
|
+
type OpenStreamFunc = func(ctx context.Context, msgHandler PacketHandler) (Writer, error)
|
|
23
23
|
|
|
24
24
|
// client implements Client with a transport.
|
|
25
25
|
type client struct {
|
|
@@ -48,7 +48,7 @@ func (c *client) Invoke(rctx context.Context, service, method string, in, out Me
|
|
|
48
48
|
if err != nil {
|
|
49
49
|
return err
|
|
50
50
|
}
|
|
51
|
-
if err := clientRPC.Start(writer, firstMsg); err != nil {
|
|
51
|
+
if err := clientRPC.Start(writer, true, firstMsg); err != nil {
|
|
52
52
|
return err
|
|
53
53
|
}
|
|
54
54
|
msgs, err := clientRPC.ReadAll()
|
|
@@ -85,11 +85,11 @@ func (c *client) NewStream(ctx context.Context, service, method string, firstMsg
|
|
|
85
85
|
if err != nil {
|
|
86
86
|
return nil, err
|
|
87
87
|
}
|
|
88
|
-
if err := clientRPC.Start(writer, firstMsgData); err != nil {
|
|
88
|
+
if err := clientRPC.Start(writer, firstMsg != nil, firstMsgData); err != nil {
|
|
89
89
|
return nil, err
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
return
|
|
92
|
+
return NewMsgStream(ctx, clientRPC.writer, clientRPC.dataCh), nil
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// _ is a type assertion
|
package/srpc/client.ts
CHANGED
|
@@ -29,36 +29,38 @@ function writeClientStream(call: ClientRPC, data: Observable<Uint8Array>) {
|
|
|
29
29
|
|
|
30
30
|
// Client implements the ts-proto Rpc interface with the drpcproto protocol.
|
|
31
31
|
export class Client implements TsProtoRpc {
|
|
32
|
-
//
|
|
33
|
-
private
|
|
34
|
-
//
|
|
35
|
-
private
|
|
32
|
+
// openStreamFn is a promise which contains the OpenStreamFunc.
|
|
33
|
+
private openStreamFn: Promise<OpenStreamFunc>
|
|
34
|
+
// _openStreamFn resolves openStreamFn.
|
|
35
|
+
private _openStreamFn?: (conn?: OpenStreamFunc, err?: Error) => void
|
|
36
36
|
|
|
37
|
-
constructor(
|
|
38
|
-
this.
|
|
37
|
+
constructor(openStreamFn?: OpenStreamFunc) {
|
|
38
|
+
this.openStreamFn = this.setOpenStreamFn(openStreamFn)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
//
|
|
42
|
-
public
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
// setOpenStreamFn updates the openStreamFn for the Client.
|
|
42
|
+
public setOpenStreamFn(
|
|
43
|
+
openStreamFn?: OpenStreamFunc
|
|
44
|
+
): Promise<OpenStreamFunc> {
|
|
45
|
+
if (this._openStreamFn) {
|
|
46
|
+
if (openStreamFn) {
|
|
47
|
+
this._openStreamFn(openStreamFn)
|
|
48
|
+
this._openStreamFn = undefined
|
|
47
49
|
}
|
|
48
50
|
} else {
|
|
49
|
-
if (
|
|
50
|
-
this.
|
|
51
|
+
if (openStreamFn) {
|
|
52
|
+
this.openStreamFn = Promise.resolve(openStreamFn)
|
|
51
53
|
} else {
|
|
52
|
-
this.
|
|
54
|
+
this.initOpenStreamFn()
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
|
-
return this.
|
|
57
|
+
return this.openStreamFn
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
//
|
|
59
|
-
private
|
|
60
|
+
// initOpenStreamFn creates the empty Promise for openStreamFn.
|
|
61
|
+
private initOpenStreamFn(): Promise<OpenStreamFunc> {
|
|
60
62
|
const openPromise = new Promise<OpenStreamFunc>((resolve, reject) => {
|
|
61
|
-
this.
|
|
63
|
+
this._openStreamFn = (conn?: OpenStreamFunc, err?: Error) => {
|
|
62
64
|
if (err) {
|
|
63
65
|
reject(err)
|
|
64
66
|
} else if (conn) {
|
|
@@ -66,8 +68,8 @@ export class Client implements TsProtoRpc {
|
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
})
|
|
69
|
-
this.
|
|
70
|
-
return this.
|
|
71
|
+
this.openStreamFn = openPromise
|
|
72
|
+
return this.openStreamFn
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
// request starts a non-streaming request.
|
|
@@ -109,7 +111,7 @@ export class Client implements TsProtoRpc {
|
|
|
109
111
|
method: string,
|
|
110
112
|
data: Uint8Array
|
|
111
113
|
): Observable<Uint8Array> {
|
|
112
|
-
const pushServerData: Pushable<Uint8Array> = pushable()
|
|
114
|
+
const pushServerData: Pushable<Uint8Array> = pushable({ objectMode: true })
|
|
113
115
|
const serverData = observableFrom(pushServerData)
|
|
114
116
|
this.startRpc(service, method, data)
|
|
115
117
|
.then(async (call) => {
|
|
@@ -132,7 +134,7 @@ export class Client implements TsProtoRpc {
|
|
|
132
134
|
method: string,
|
|
133
135
|
data: Observable<Uint8Array>
|
|
134
136
|
): Observable<Uint8Array> {
|
|
135
|
-
const pushServerData: Pushable<Uint8Array> = pushable()
|
|
137
|
+
const pushServerData: Pushable<Uint8Array> = pushable({ objectMode: true })
|
|
136
138
|
const serverData = observableFrom(pushServerData)
|
|
137
139
|
this.startRpc(service, method, null)
|
|
138
140
|
.then(async (call) => {
|
|
@@ -168,8 +170,8 @@ export class Client implements TsProtoRpc {
|
|
|
168
170
|
rpcMethod: string,
|
|
169
171
|
data: Uint8Array | null
|
|
170
172
|
): Promise<ClientRPC> {
|
|
171
|
-
const
|
|
172
|
-
const conn = await
|
|
173
|
+
const openStreamFn = await this.openStreamFn
|
|
174
|
+
const conn = await openStreamFn()
|
|
173
175
|
const call = new ClientRPC(rpcService, rpcMethod)
|
|
174
176
|
pipe(
|
|
175
177
|
conn,
|