starpc 0.4.9 → 0.5.2
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 +1 -0
- package/README.md +20 -10
- package/dist/echo/client-test.d.ts +1 -0
- package/dist/echo/client-test.js +20 -18
- package/dist/echo/echo.pb.d.ts +162 -10
- package/dist/echo/echo.pb.js +48 -5
- package/dist/echo/server.d.ts +8 -4
- package/dist/echo/server.js +29 -37
- package/dist/rpcstream/rpcstream.d.ts +6 -6
- package/dist/rpcstream/rpcstream.js +92 -51
- package/dist/rpcstream/rpcstream.pb.d.ts +44 -0
- package/dist/rpcstream/rpcstream.pb.js +151 -4
- package/dist/srpc/client.d.ts +3 -4
- package/dist/srpc/client.js +12 -46
- package/dist/srpc/common-rpc.d.ts +3 -2
- package/dist/srpc/common-rpc.js +12 -0
- package/dist/srpc/definition.d.ts +3 -3
- package/dist/srpc/handler.d.ts +2 -3
- package/dist/srpc/handler.js +5 -22
- package/dist/srpc/index.d.ts +2 -2
- package/dist/srpc/index.js +2 -2
- package/dist/srpc/packet.js +0 -32
- package/dist/srpc/pushable.d.ts +2 -0
- package/dist/srpc/pushable.js +13 -0
- package/dist/srpc/rpcproto.pb.d.ts +6 -0
- package/dist/srpc/rpcproto.pb.js +84 -0
- package/dist/srpc/server.d.ts +1 -0
- package/dist/srpc/server.js +7 -0
- package/dist/srpc/ts-proto-rpc.d.ts +3 -4
- package/e2e/e2e.ts +4 -3
- package/e2e/e2e_test.go +24 -1
- package/echo/client-test.ts +23 -18
- package/echo/echo.pb.go +33 -20
- package/echo/echo.pb.ts +75 -20
- package/echo/echo.proto +4 -0
- package/echo/echo_srpc.pb.go +77 -0
- package/echo/server.go +18 -0
- package/echo/server.ts +47 -41
- package/integration/integration.go +1 -2
- package/integration/integration.ts +5 -1
- package/integration/integration_srpc.pb.go +139 -0
- package/package.json +13 -9
- package/patches/{ts-poet+4.14.0.patch → ts-poet+4.15.0.patch} +1 -1
- package/patches/ts-proto+1.116.0.patch +14 -0
- package/srpc/client.ts +16 -50
- package/srpc/common-rpc.ts +14 -2
- package/srpc/definition.ts +3 -3
- package/srpc/handler.ts +17 -34
- package/srpc/index.ts +2 -2
- package/srpc/muxed-conn.go +2 -2
- package/srpc/packet-rw.go +4 -6
- package/srpc/packet.ts +0 -33
- package/srpc/pushable.ts +17 -0
- package/srpc/rpcproto.pb.ts +106 -0
- package/srpc/server-pipe.go +2 -2
- package/srpc/server.go +2 -2
- package/srpc/server.ts +8 -0
- package/srpc/ts-proto-rpc.ts +4 -6
- package/srpc/websocket.go +2 -2
- package/dist/echo/sever.d.ts +0 -0
- package/dist/echo/sever.js +0 -1
- package/dist/srpc/observable-source.d.ts +0 -9
- package/dist/srpc/observable-source.js +0 -25
- package/echo/sever.ts +0 -0
- package/srpc/observable-source.ts +0 -40
package/echo/echo.pb.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import Long from 'long'
|
|
3
|
+
import { RpcStreamPacket } from '../rpcstream/rpcstream.pb.js'
|
|
3
4
|
import * as _m0 from 'protobufjs/minimal'
|
|
4
|
-
import { Observable } from 'rxjs'
|
|
5
|
-
import { map } from 'rxjs/operators'
|
|
6
5
|
|
|
7
6
|
export const protobufPackage = 'echo'
|
|
8
7
|
|
|
@@ -44,6 +43,40 @@ export const EchoMsg = {
|
|
|
44
43
|
return message
|
|
45
44
|
},
|
|
46
45
|
|
|
46
|
+
// encodeTransform encodes a source of message objects.
|
|
47
|
+
// Transform<EchoMsg, Uint8Array>
|
|
48
|
+
async *encodeTransform(
|
|
49
|
+
source: AsyncIterable<EchoMsg | EchoMsg[]> | Iterable<EchoMsg | EchoMsg[]>
|
|
50
|
+
): AsyncIterable<Uint8Array> {
|
|
51
|
+
for await (const pkt of source) {
|
|
52
|
+
if (Array.isArray(pkt)) {
|
|
53
|
+
for (const p of pkt) {
|
|
54
|
+
yield* [EchoMsg.encode(p).finish()]
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
yield* [EchoMsg.encode(pkt).finish()]
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
// decodeTransform decodes a source of encoded messages.
|
|
63
|
+
// Transform<Uint8Array, EchoMsg>
|
|
64
|
+
async *decodeTransform(
|
|
65
|
+
source:
|
|
66
|
+
| AsyncIterable<Uint8Array | Uint8Array[]>
|
|
67
|
+
| Iterable<Uint8Array | Uint8Array[]>
|
|
68
|
+
): AsyncIterable<EchoMsg> {
|
|
69
|
+
for await (const pkt of source) {
|
|
70
|
+
if (Array.isArray(pkt)) {
|
|
71
|
+
for (const p of pkt) {
|
|
72
|
+
yield* [EchoMsg.decode(p)]
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
yield* [EchoMsg.decode(pkt)]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
|
|
47
80
|
fromJSON(object: any): EchoMsg {
|
|
48
81
|
return {
|
|
49
82
|
body: isSet(object.body) ? String(object.body) : '',
|
|
@@ -68,11 +101,15 @@ export interface Echoer {
|
|
|
68
101
|
/** Echo returns the given message. */
|
|
69
102
|
Echo(request: EchoMsg): Promise<EchoMsg>
|
|
70
103
|
/** EchoServerStream is an example of a server -> client one-way stream. */
|
|
71
|
-
EchoServerStream(request: EchoMsg):
|
|
104
|
+
EchoServerStream(request: EchoMsg): AsyncIterable<EchoMsg>
|
|
72
105
|
/** EchoClientStream is an example of client->server one-way stream. */
|
|
73
|
-
EchoClientStream(request:
|
|
106
|
+
EchoClientStream(request: AsyncIterable<EchoMsg>): Promise<EchoMsg>
|
|
74
107
|
/** EchoBidiStream is an example of a two-way stream. */
|
|
75
|
-
EchoBidiStream(request:
|
|
108
|
+
EchoBidiStream(request: AsyncIterable<EchoMsg>): AsyncIterable<EchoMsg>
|
|
109
|
+
/** RpcStream opens a nested rpc call stream. */
|
|
110
|
+
RpcStream(
|
|
111
|
+
request: AsyncIterable<RpcStreamPacket>
|
|
112
|
+
): AsyncIterable<RpcStreamPacket>
|
|
76
113
|
}
|
|
77
114
|
|
|
78
115
|
export class EchoerClientImpl implements Echoer {
|
|
@@ -83,6 +120,7 @@ export class EchoerClientImpl implements Echoer {
|
|
|
83
120
|
this.EchoServerStream = this.EchoServerStream.bind(this)
|
|
84
121
|
this.EchoClientStream = this.EchoClientStream.bind(this)
|
|
85
122
|
this.EchoBidiStream = this.EchoBidiStream.bind(this)
|
|
123
|
+
this.RpcStream = this.RpcStream.bind(this)
|
|
86
124
|
}
|
|
87
125
|
Echo(request: EchoMsg): Promise<EchoMsg> {
|
|
88
126
|
const data = EchoMsg.encode(request).finish()
|
|
@@ -90,20 +128,18 @@ export class EchoerClientImpl implements Echoer {
|
|
|
90
128
|
return promise.then((data) => EchoMsg.decode(new _m0.Reader(data)))
|
|
91
129
|
}
|
|
92
130
|
|
|
93
|
-
EchoServerStream(request: EchoMsg):
|
|
131
|
+
EchoServerStream(request: EchoMsg): AsyncIterable<EchoMsg> {
|
|
94
132
|
const data = EchoMsg.encode(request).finish()
|
|
95
133
|
const result = this.rpc.serverStreamingRequest(
|
|
96
134
|
'echo.Echoer',
|
|
97
135
|
'EchoServerStream',
|
|
98
136
|
data
|
|
99
137
|
)
|
|
100
|
-
return
|
|
138
|
+
return EchoMsg.decodeTransform(result)
|
|
101
139
|
}
|
|
102
140
|
|
|
103
|
-
EchoClientStream(request:
|
|
104
|
-
const data =
|
|
105
|
-
map((request) => EchoMsg.encode(request).finish())
|
|
106
|
-
)
|
|
141
|
+
EchoClientStream(request: AsyncIterable<EchoMsg>): Promise<EchoMsg> {
|
|
142
|
+
const data = EchoMsg.encodeTransform(request)
|
|
107
143
|
const promise = this.rpc.clientStreamingRequest(
|
|
108
144
|
'echo.Echoer',
|
|
109
145
|
'EchoClientStream',
|
|
@@ -112,16 +148,26 @@ export class EchoerClientImpl implements Echoer {
|
|
|
112
148
|
return promise.then((data) => EchoMsg.decode(new _m0.Reader(data)))
|
|
113
149
|
}
|
|
114
150
|
|
|
115
|
-
EchoBidiStream(request:
|
|
116
|
-
const data =
|
|
117
|
-
map((request) => EchoMsg.encode(request).finish())
|
|
118
|
-
)
|
|
151
|
+
EchoBidiStream(request: AsyncIterable<EchoMsg>): AsyncIterable<EchoMsg> {
|
|
152
|
+
const data = EchoMsg.encodeTransform(request)
|
|
119
153
|
const result = this.rpc.bidirectionalStreamingRequest(
|
|
120
154
|
'echo.Echoer',
|
|
121
155
|
'EchoBidiStream',
|
|
122
156
|
data
|
|
123
157
|
)
|
|
124
|
-
return
|
|
158
|
+
return EchoMsg.decodeTransform(result)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
RpcStream(
|
|
162
|
+
request: AsyncIterable<RpcStreamPacket>
|
|
163
|
+
): AsyncIterable<RpcStreamPacket> {
|
|
164
|
+
const data = RpcStreamPacket.encodeTransform(request)
|
|
165
|
+
const result = this.rpc.bidirectionalStreamingRequest(
|
|
166
|
+
'echo.Echoer',
|
|
167
|
+
'RpcStream',
|
|
168
|
+
data
|
|
169
|
+
)
|
|
170
|
+
return RpcStreamPacket.decodeTransform(result)
|
|
125
171
|
}
|
|
126
172
|
}
|
|
127
173
|
|
|
@@ -167,6 +213,15 @@ export const EchoerDefinition = {
|
|
|
167
213
|
responseStream: true,
|
|
168
214
|
options: {},
|
|
169
215
|
},
|
|
216
|
+
/** RpcStream opens a nested rpc call stream. */
|
|
217
|
+
rpcStream: {
|
|
218
|
+
name: 'RpcStream',
|
|
219
|
+
requestType: RpcStreamPacket,
|
|
220
|
+
requestStream: true,
|
|
221
|
+
responseType: RpcStreamPacket,
|
|
222
|
+
responseStream: true,
|
|
223
|
+
options: {},
|
|
224
|
+
},
|
|
170
225
|
},
|
|
171
226
|
} as const
|
|
172
227
|
|
|
@@ -179,18 +234,18 @@ interface Rpc {
|
|
|
179
234
|
clientStreamingRequest(
|
|
180
235
|
service: string,
|
|
181
236
|
method: string,
|
|
182
|
-
data:
|
|
237
|
+
data: AsyncIterable<Uint8Array>
|
|
183
238
|
): Promise<Uint8Array>
|
|
184
239
|
serverStreamingRequest(
|
|
185
240
|
service: string,
|
|
186
241
|
method: string,
|
|
187
242
|
data: Uint8Array
|
|
188
|
-
):
|
|
243
|
+
): AsyncIterable<Uint8Array>
|
|
189
244
|
bidirectionalStreamingRequest(
|
|
190
245
|
service: string,
|
|
191
246
|
method: string,
|
|
192
|
-
data:
|
|
193
|
-
):
|
|
247
|
+
data: AsyncIterable<Uint8Array>
|
|
248
|
+
): AsyncIterable<Uint8Array>
|
|
194
249
|
}
|
|
195
250
|
|
|
196
251
|
type Builtin =
|
package/echo/echo.proto
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
syntax = "proto3";
|
|
2
2
|
package echo;
|
|
3
3
|
|
|
4
|
+
import "github.com/aperturerobotics/starpc/rpcstream/rpcstream.proto";
|
|
5
|
+
|
|
4
6
|
// Echoer service returns the given message.
|
|
5
7
|
service Echoer {
|
|
6
8
|
// Echo returns the given message.
|
|
@@ -11,6 +13,8 @@ service Echoer {
|
|
|
11
13
|
rpc EchoClientStream(stream EchoMsg) returns (EchoMsg);
|
|
12
14
|
// EchoBidiStream is an example of a two-way stream.
|
|
13
15
|
rpc EchoBidiStream(stream EchoMsg) returns (stream EchoMsg);
|
|
16
|
+
// RpcStream opens a nested rpc call stream.
|
|
17
|
+
rpc RpcStream(stream .rpcstream.RpcStreamPacket) returns (stream .rpcstream.RpcStreamPacket);
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
// EchoMsg is the message body for Echo.
|
package/echo/echo_srpc.pb.go
CHANGED
|
@@ -7,6 +7,7 @@ package echo
|
|
|
7
7
|
import (
|
|
8
8
|
context "context"
|
|
9
9
|
|
|
10
|
+
rpcstream "github.com/aperturerobotics/starpc/rpcstream"
|
|
10
11
|
srpc "github.com/aperturerobotics/starpc/srpc"
|
|
11
12
|
)
|
|
12
13
|
|
|
@@ -17,6 +18,7 @@ type SRPCEchoerClient interface {
|
|
|
17
18
|
EchoServerStream(ctx context.Context, in *EchoMsg) (SRPCEchoer_EchoServerStreamClient, error)
|
|
18
19
|
EchoClientStream(ctx context.Context) (SRPCEchoer_EchoClientStreamClient, error)
|
|
19
20
|
EchoBidiStream(ctx context.Context) (SRPCEchoer_EchoBidiStreamClient, error)
|
|
21
|
+
RpcStream(ctx context.Context) (SRPCEchoer_RpcStreamClient, error)
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
type srpcEchoerClient struct {
|
|
@@ -149,11 +151,48 @@ func (x *srpcEchoer_EchoBidiStreamClient) RecvTo(m *EchoMsg) error {
|
|
|
149
151
|
return x.MsgRecv(m)
|
|
150
152
|
}
|
|
151
153
|
|
|
154
|
+
func (c *srpcEchoerClient) RpcStream(ctx context.Context) (SRPCEchoer_RpcStreamClient, error) {
|
|
155
|
+
stream, err := c.cc.NewStream(ctx, "echo.Echoer", "RpcStream", nil)
|
|
156
|
+
if err != nil {
|
|
157
|
+
return nil, err
|
|
158
|
+
}
|
|
159
|
+
strm := &srpcEchoer_RpcStreamClient{stream}
|
|
160
|
+
return strm, nil
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
type SRPCEchoer_RpcStreamClient interface {
|
|
164
|
+
srpc.Stream
|
|
165
|
+
Send(*rpcstream.RpcStreamPacket) error
|
|
166
|
+
Recv() (*rpcstream.RpcStreamPacket, error)
|
|
167
|
+
RecvTo(*rpcstream.RpcStreamPacket) error
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
type srpcEchoer_RpcStreamClient struct {
|
|
171
|
+
srpc.Stream
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
func (x *srpcEchoer_RpcStreamClient) Send(m *rpcstream.RpcStreamPacket) error {
|
|
175
|
+
return x.MsgSend(m)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
func (x *srpcEchoer_RpcStreamClient) Recv() (*rpcstream.RpcStreamPacket, error) {
|
|
179
|
+
m := new(rpcstream.RpcStreamPacket)
|
|
180
|
+
if err := x.MsgRecv(m); err != nil {
|
|
181
|
+
return nil, err
|
|
182
|
+
}
|
|
183
|
+
return m, nil
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
func (x *srpcEchoer_RpcStreamClient) RecvTo(m *rpcstream.RpcStreamPacket) error {
|
|
187
|
+
return x.MsgRecv(m)
|
|
188
|
+
}
|
|
189
|
+
|
|
152
190
|
type SRPCEchoerServer interface {
|
|
153
191
|
Echo(context.Context, *EchoMsg) (*EchoMsg, error)
|
|
154
192
|
EchoServerStream(*EchoMsg, SRPCEchoer_EchoServerStreamStream) error
|
|
155
193
|
EchoClientStream(SRPCEchoer_EchoClientStreamStream) error
|
|
156
194
|
EchoBidiStream(SRPCEchoer_EchoBidiStreamStream) error
|
|
195
|
+
RpcStream(SRPCEchoer_RpcStreamStream) error
|
|
157
196
|
}
|
|
158
197
|
|
|
159
198
|
type SRPCEchoerUnimplementedServer struct{}
|
|
@@ -174,6 +213,10 @@ func (s *SRPCEchoerUnimplementedServer) EchoBidiStream(SRPCEchoer_EchoBidiStream
|
|
|
174
213
|
return srpc.ErrUnimplemented
|
|
175
214
|
}
|
|
176
215
|
|
|
216
|
+
func (s *SRPCEchoerUnimplementedServer) RpcStream(SRPCEchoer_RpcStreamStream) error {
|
|
217
|
+
return srpc.ErrUnimplemented
|
|
218
|
+
}
|
|
219
|
+
|
|
177
220
|
const SRPCEchoerServiceID = "echo.Echoer"
|
|
178
221
|
|
|
179
222
|
type SRPCEchoerHandler struct {
|
|
@@ -188,6 +231,7 @@ func (SRPCEchoerHandler) GetMethodIDs() []string {
|
|
|
188
231
|
"EchoServerStream",
|
|
189
232
|
"EchoClientStream",
|
|
190
233
|
"EchoBidiStream",
|
|
234
|
+
"RpcStream",
|
|
191
235
|
}
|
|
192
236
|
}
|
|
193
237
|
|
|
@@ -208,6 +252,8 @@ func (d *SRPCEchoerHandler) InvokeMethod(
|
|
|
208
252
|
return true, d.InvokeMethod_EchoClientStream(d.impl, strm)
|
|
209
253
|
case "EchoBidiStream":
|
|
210
254
|
return true, d.InvokeMethod_EchoBidiStream(d.impl, strm)
|
|
255
|
+
case "RpcStream":
|
|
256
|
+
return true, d.InvokeMethod_RpcStream(d.impl, strm)
|
|
211
257
|
default:
|
|
212
258
|
return false, nil
|
|
213
259
|
}
|
|
@@ -244,6 +290,11 @@ func (SRPCEchoerHandler) InvokeMethod_EchoBidiStream(impl SRPCEchoerServer, strm
|
|
|
244
290
|
return impl.EchoBidiStream(clientStrm)
|
|
245
291
|
}
|
|
246
292
|
|
|
293
|
+
func (SRPCEchoerHandler) InvokeMethod_RpcStream(impl SRPCEchoerServer, strm srpc.Stream) error {
|
|
294
|
+
clientStrm := &srpcEchoer_RpcStreamStream{strm}
|
|
295
|
+
return impl.RpcStream(clientStrm)
|
|
296
|
+
}
|
|
297
|
+
|
|
247
298
|
func SRPCRegisterEchoer(mux srpc.Mux, impl SRPCEchoerServer) error {
|
|
248
299
|
return mux.Register(&SRPCEchoerHandler{impl: impl})
|
|
249
300
|
}
|
|
@@ -331,3 +382,29 @@ func (x *srpcEchoer_EchoBidiStreamStream) Recv() (*EchoMsg, error) {
|
|
|
331
382
|
func (x *srpcEchoer_EchoBidiStreamStream) RecvTo(m *EchoMsg) error {
|
|
332
383
|
return x.MsgRecv(m)
|
|
333
384
|
}
|
|
385
|
+
|
|
386
|
+
type SRPCEchoer_RpcStreamStream interface {
|
|
387
|
+
srpc.Stream
|
|
388
|
+
Send(*rpcstream.RpcStreamPacket) error
|
|
389
|
+
Recv() (*rpcstream.RpcStreamPacket, error)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
type srpcEchoer_RpcStreamStream struct {
|
|
393
|
+
srpc.Stream
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
func (x *srpcEchoer_RpcStreamStream) Send(m *rpcstream.RpcStreamPacket) error {
|
|
397
|
+
return x.MsgSend(m)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
func (x *srpcEchoer_RpcStreamStream) Recv() (*rpcstream.RpcStreamPacket, error) {
|
|
401
|
+
m := new(rpcstream.RpcStreamPacket)
|
|
402
|
+
if err := x.MsgRecv(m); err != nil {
|
|
403
|
+
return nil, err
|
|
404
|
+
}
|
|
405
|
+
return m, nil
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
func (x *srpcEchoer_RpcStreamStream) RecvTo(m *rpcstream.RpcStreamPacket) error {
|
|
409
|
+
return x.MsgRecv(m)
|
|
410
|
+
}
|
package/echo/server.go
CHANGED
|
@@ -6,11 +6,19 @@ import (
|
|
|
6
6
|
"io"
|
|
7
7
|
"time"
|
|
8
8
|
|
|
9
|
+
rpcstream "github.com/aperturerobotics/starpc/rpcstream"
|
|
10
|
+
srpc "github.com/aperturerobotics/starpc/srpc"
|
|
9
11
|
"google.golang.org/protobuf/proto"
|
|
10
12
|
)
|
|
11
13
|
|
|
12
14
|
// EchoServer implements the server side of Echo.
|
|
13
15
|
type EchoServer struct {
|
|
16
|
+
rpcStreamMux srpc.Mux
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// NewEchoServer constructs a EchoServer with a RpcStream mux.
|
|
20
|
+
func NewEchoServer(rpcStreamMux srpc.Mux) *EchoServer {
|
|
21
|
+
return &EchoServer{rpcStreamMux: rpcStreamMux}
|
|
14
22
|
}
|
|
15
23
|
|
|
16
24
|
// Echo implements echo.SRPCEchoerServer
|
|
@@ -69,5 +77,15 @@ func (s *EchoServer) EchoBidiStream(strm SRPCEchoer_EchoBidiStreamStream) error
|
|
|
69
77
|
}
|
|
70
78
|
}
|
|
71
79
|
|
|
80
|
+
// RpcStream runs a rpc stream
|
|
81
|
+
func (r *EchoServer) RpcStream(stream SRPCEchoer_RpcStreamStream) error {
|
|
82
|
+
return rpcstream.HandleRpcStream(stream, func(ctx context.Context, componentID string) (srpc.Mux, error) {
|
|
83
|
+
if r.rpcStreamMux == nil {
|
|
84
|
+
return nil, errors.New("not implemented")
|
|
85
|
+
}
|
|
86
|
+
return r.rpcStreamMux, nil
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
72
90
|
// _ is a type assertion
|
|
73
91
|
var _ SRPCEchoerServer = ((*EchoServer)(nil))
|
package/echo/server.ts
CHANGED
|
@@ -1,57 +1,63 @@
|
|
|
1
|
-
import { Observable, from as observableFrom } from 'rxjs'
|
|
2
1
|
import { Echoer, EchoMsg } from './echo.pb.js'
|
|
3
2
|
import { pushable, Pushable } from 'it-pushable'
|
|
3
|
+
import first from 'it-first'
|
|
4
|
+
import { Server } from '../srpc/server.js'
|
|
5
|
+
import { writeToPushable } from '../srpc/pushable.js'
|
|
6
|
+
import { RpcStreamPacket } from '../rpcstream/rpcstream.pb.js'
|
|
7
|
+
import { handleRpcStream } from '../rpcstream/rpcstream.js'
|
|
4
8
|
|
|
5
9
|
// EchoServer implements the Echoer server.
|
|
6
10
|
export class EchoerServer implements Echoer {
|
|
11
|
+
// proxyServer is the server used for RpcStream requests.
|
|
12
|
+
private proxyServer?: Server
|
|
13
|
+
|
|
14
|
+
constructor(proxyServer?: Server) {
|
|
15
|
+
this.proxyServer = proxyServer
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
public async Echo(request: EchoMsg): Promise<EchoMsg> {
|
|
8
19
|
return request
|
|
9
20
|
}
|
|
10
21
|
|
|
11
|
-
public EchoServerStream(request: EchoMsg):
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
yield request
|
|
17
|
-
await new Promise((resolve) => setTimeout(resolve, 200))
|
|
18
|
-
}
|
|
19
|
-
})()
|
|
20
|
-
)
|
|
22
|
+
public async *EchoServerStream(request: EchoMsg): AsyncIterable<EchoMsg> {
|
|
23
|
+
for (let i = 0; i < 5; i++) {
|
|
24
|
+
yield request
|
|
25
|
+
await new Promise((resolve) => setTimeout(resolve, 200))
|
|
26
|
+
}
|
|
21
27
|
}
|
|
22
28
|
|
|
23
|
-
public EchoClientStream(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
complete() {
|
|
33
|
-
reject(new Error('none received'))
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
})
|
|
29
|
+
public async EchoClientStream(
|
|
30
|
+
request: AsyncIterable<EchoMsg>
|
|
31
|
+
): Promise<EchoMsg> {
|
|
32
|
+
// return the first message sent by the client.
|
|
33
|
+
const message = await first(request)
|
|
34
|
+
if (!message) {
|
|
35
|
+
throw new Error('received no messages')
|
|
36
|
+
}
|
|
37
|
+
return message
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
public EchoBidiStream(
|
|
40
|
+
public EchoBidiStream(
|
|
41
|
+
request: AsyncIterable<EchoMsg>
|
|
42
|
+
): AsyncIterable<EchoMsg> {
|
|
40
43
|
// build result observable
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
const result: Pushable<EchoMsg> = pushable({ objectMode: true })
|
|
45
|
+
result.push({ body: 'hello from server' })
|
|
46
|
+
writeToPushable(request, result)
|
|
47
|
+
return result
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public RpcStream(
|
|
51
|
+
request: AsyncIterable<RpcStreamPacket>
|
|
52
|
+
): AsyncIterable<RpcStreamPacket> {
|
|
53
|
+
return handleRpcStream(
|
|
54
|
+
request[Symbol.asyncIterator](),
|
|
55
|
+
async (_componentId: string): Promise<Server> => {
|
|
56
|
+
if (!this.proxyServer) {
|
|
57
|
+
throw new Error('rpc stream proxy server not set')
|
|
58
|
+
}
|
|
59
|
+
return this.proxyServer
|
|
60
|
+
}
|
|
61
|
+
)
|
|
56
62
|
}
|
|
57
63
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebSocketConn } from '../srpc/websocket.js'
|
|
2
|
-
import { runClientTest } from '../echo/client-test.js'
|
|
2
|
+
import { runClientTest, runRpcStreamTest } from '../echo/client-test.js'
|
|
3
3
|
import WebSocket from 'isomorphic-ws'
|
|
4
4
|
|
|
5
5
|
async function runRPC() {
|
|
@@ -9,7 +9,11 @@ async function runRPC() {
|
|
|
9
9
|
const channel = new WebSocketConn(ws)
|
|
10
10
|
const client = channel.buildClient()
|
|
11
11
|
|
|
12
|
+
console.log('Running client test via WebSocket..')
|
|
12
13
|
await runClientTest(client)
|
|
14
|
+
|
|
15
|
+
console.log('Running RpcStream test via WebSocket..')
|
|
16
|
+
await runRpcStreamTest(client)
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
runRPC()
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Code generated by protoc-gen-srpc. DO NOT EDIT.
|
|
2
|
+
// protoc-gen-srpc version: v0.0.0-20220611014014-aa9dc5523865
|
|
3
|
+
// source: github.com/aperturerobotics/starpc/integration/integration.proto
|
|
4
|
+
|
|
5
|
+
package main
|
|
6
|
+
|
|
7
|
+
import (
|
|
8
|
+
context "context"
|
|
9
|
+
|
|
10
|
+
rpcstream "github.com/aperturerobotics/starpc/rpcstream"
|
|
11
|
+
srpc "github.com/aperturerobotics/starpc/srpc"
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
type SRPCIntegrationServiceClient interface {
|
|
15
|
+
SRPCClient() srpc.Client
|
|
16
|
+
|
|
17
|
+
RpcStream(ctx context.Context) (SRPCIntegrationService_RpcStreamClient, error)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type srpcIntegrationServiceClient struct {
|
|
21
|
+
cc srpc.Client
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func NewSRPCIntegrationServiceClient(cc srpc.Client) SRPCIntegrationServiceClient {
|
|
25
|
+
return &srpcIntegrationServiceClient{cc}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func (c *srpcIntegrationServiceClient) SRPCClient() srpc.Client { return c.cc }
|
|
29
|
+
|
|
30
|
+
func (c *srpcIntegrationServiceClient) RpcStream(ctx context.Context) (SRPCIntegrationService_RpcStreamClient, error) {
|
|
31
|
+
stream, err := c.cc.NewStream(ctx, "main.IntegrationService", "RpcStream", nil)
|
|
32
|
+
if err != nil {
|
|
33
|
+
return nil, err
|
|
34
|
+
}
|
|
35
|
+
strm := &srpcIntegrationService_RpcStreamClient{stream}
|
|
36
|
+
return strm, nil
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type SRPCIntegrationService_RpcStreamClient interface {
|
|
40
|
+
srpc.Stream
|
|
41
|
+
Send(*rpcstream.RpcStreamPacket) error
|
|
42
|
+
Recv() (*rpcstream.RpcStreamPacket, error)
|
|
43
|
+
RecvTo(*rpcstream.RpcStreamPacket) error
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type srpcIntegrationService_RpcStreamClient struct {
|
|
47
|
+
srpc.Stream
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
func (x *srpcIntegrationService_RpcStreamClient) Send(m *rpcstream.RpcStreamPacket) error {
|
|
51
|
+
return x.MsgSend(m)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
func (x *srpcIntegrationService_RpcStreamClient) Recv() (*rpcstream.RpcStreamPacket, error) {
|
|
55
|
+
m := new(rpcstream.RpcStreamPacket)
|
|
56
|
+
if err := x.MsgRecv(m); err != nil {
|
|
57
|
+
return nil, err
|
|
58
|
+
}
|
|
59
|
+
return m, nil
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
func (x *srpcIntegrationService_RpcStreamClient) RecvTo(m *rpcstream.RpcStreamPacket) error {
|
|
63
|
+
return x.MsgRecv(m)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type SRPCIntegrationServiceServer interface {
|
|
67
|
+
RpcStream(SRPCIntegrationService_RpcStreamStream) error
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type SRPCIntegrationServiceUnimplementedServer struct{}
|
|
71
|
+
|
|
72
|
+
func (s *SRPCIntegrationServiceUnimplementedServer) RpcStream(SRPCIntegrationService_RpcStreamStream) error {
|
|
73
|
+
return srpc.ErrUnimplemented
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const SRPCIntegrationServiceServiceID = "main.IntegrationService"
|
|
77
|
+
|
|
78
|
+
type SRPCIntegrationServiceHandler struct {
|
|
79
|
+
impl SRPCIntegrationServiceServer
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
func (SRPCIntegrationServiceHandler) GetServiceID() string { return SRPCIntegrationServiceServiceID }
|
|
83
|
+
|
|
84
|
+
func (SRPCIntegrationServiceHandler) GetMethodIDs() []string {
|
|
85
|
+
return []string{
|
|
86
|
+
"RpcStream",
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
func (d *SRPCIntegrationServiceHandler) InvokeMethod(
|
|
91
|
+
serviceID, methodID string,
|
|
92
|
+
strm srpc.Stream,
|
|
93
|
+
) (bool, error) {
|
|
94
|
+
if serviceID != "" && serviceID != d.GetServiceID() {
|
|
95
|
+
return false, nil
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
switch methodID {
|
|
99
|
+
case "RpcStream":
|
|
100
|
+
return true, d.InvokeMethod_RpcStream(d.impl, strm)
|
|
101
|
+
default:
|
|
102
|
+
return false, nil
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
func (SRPCIntegrationServiceHandler) InvokeMethod_RpcStream(impl SRPCIntegrationServiceServer, strm srpc.Stream) error {
|
|
107
|
+
clientStrm := &srpcIntegrationService_RpcStreamStream{strm}
|
|
108
|
+
return impl.RpcStream(clientStrm)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
func SRPCRegisterIntegrationService(mux srpc.Mux, impl SRPCIntegrationServiceServer) error {
|
|
112
|
+
return mux.Register(&SRPCIntegrationServiceHandler{impl: impl})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
type SRPCIntegrationService_RpcStreamStream interface {
|
|
116
|
+
srpc.Stream
|
|
117
|
+
Send(*rpcstream.RpcStreamPacket) error
|
|
118
|
+
Recv() (*rpcstream.RpcStreamPacket, error)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
type srpcIntegrationService_RpcStreamStream struct {
|
|
122
|
+
srpc.Stream
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
func (x *srpcIntegrationService_RpcStreamStream) Send(m *rpcstream.RpcStreamPacket) error {
|
|
126
|
+
return x.MsgSend(m)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
func (x *srpcIntegrationService_RpcStreamStream) Recv() (*rpcstream.RpcStreamPacket, error) {
|
|
130
|
+
m := new(rpcstream.RpcStreamPacket)
|
|
131
|
+
if err := x.MsgRecv(m); err != nil {
|
|
132
|
+
return nil, err
|
|
133
|
+
}
|
|
134
|
+
return m, nil
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
func (x *srpcIntegrationService_RpcStreamStream) RecvTo(m *rpcstream.RpcStreamPacket) error {
|
|
138
|
+
return x.MsgRecv(m)
|
|
139
|
+
}
|