starpc 0.3.4 → 0.3.5

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Stream RPC
2
2
 
3
- **starpc** implements [Proto3 services] in both TypeScript and Go.
3
+ **starpc** implements [Proto3 services] (server & client) in both TypeScript and Go.
4
4
 
5
5
  [Proto3 services]: https://developers.google.com/protocol-buffers/docs/proto3#services
6
6
 
@@ -13,8 +13,6 @@ Can use any Stream multiplexer: defaults to [libp2p-mplex] over a WebSocket.
13
13
 
14
14
  [libp2p-mplex]: https://github.com/libp2p/js-libp2p-mplex
15
15
 
16
- Note: the server has not yet been implemented in TypeScript.
17
-
18
16
  # Usage
19
17
 
20
18
  Starting with the [protobuf-project] repository on the "starpc" branch.
@@ -30,6 +28,8 @@ The demo/boilerplate project implements the Echo example below.
30
28
 
31
29
  [protobuf-project]: https://github.com/aperturerobotics/protobuf-project/tree/starpc
32
30
 
31
+ This repository uses protowrap, see the [Makefile](./Makefile).
32
+
33
33
  ## Protobuf
34
34
 
35
35
  The following examples use the [echo](./echo/echo.proto) protobuf sample.
@@ -56,9 +56,9 @@ message EchoMsg {
56
56
  }
57
57
  ```
58
58
 
59
- ## Go: Server & Client
59
+ ## Go
60
60
 
61
- A basic example can be found in the [e2e test]:
61
+ This example demonstrates both the server and client:
62
62
 
63
63
  ```go
64
64
  // construct the server
@@ -96,39 +96,58 @@ if out.GetBody() != bodyTxt {
96
96
 
97
97
  See the ts-proto README to generate the TypeScript for your protobufs.
98
98
 
99
- Also check out the [integration](./integration/integration.ts) test.
99
+ For an example of Go <-> TypeScript interop, see the [integration] test. For an
100
+ example of TypeScript <-> TypeScript interop, see the [e2e] test.
100
101
 
101
- Supports any AsyncIterable communication channel with an included implementation
102
- for WebSockets.
102
+ [e2e]: ./e2e/e2e.ts
103
+ [integration]: ./integration/integration.ts
103
104
 
104
- This repository uses protowrap, see the [Makefile](./Makefile).
105
-
106
- `WebSocketConn` uses [js-libp2p-mplex] to multiplex streams over the WebSocket.
105
+ Supports any AsyncIterable communication channel. `DuplexConn`,
106
+ `MessagePortConn`, and `WebSocketConn` use [js-libp2p-mplex] to multiplex
107
+ streams, but any multiplexer can be used.
107
108
 
108
109
  [js-libp2p-mplex]: https://github.com/libp2p/js-libp2p-mplex
109
110
 
110
- ### Server
111
+ This example demonstrates both the server and client:
111
112
 
112
113
  ```typescript
113
- import { WebSocketConn, Server, createMux } from '../srpc'
114
- import { EchoerClientImpl } from '../echo/echo'
114
+ import { pipe } from 'it-pipe'
115
+ import { createHandler, createMux, Server, Client, Conn } from 'srpc'
116
+ import { EchoerDefinition, EchoerServer, runClientTest } from 'srpc/echo'
115
117
 
116
118
  const mux = createMux()
117
- mux.register(TODO)
119
+ const echoer = new EchoerServer()
120
+ mux.register(createHandler(EchoerDefinition, echoer))
118
121
  const server = new Server(mux)
119
122
 
120
- // TODO: accept a WebSocket-like object.
121
- const ws = TODO
122
- const channel = new WebSocketConn(ws, server)
123
- // incoming streams will be handled by server.
123
+ const clientConn = new Conn()
124
+ const serverConn = new Conn(server)
125
+ pipe(clientConn, serverConn, clientConn)
126
+ const client = new Client(clientConn.buildOpenStreamFunc())
127
+
128
+ console.log('Calling Echo: unary call...')
129
+ let result = await demoServiceClient.Echo({
130
+ body: 'Hello world!',
131
+ })
132
+ console.log('success: output', result.body)
133
+
134
+ const clientRequestStream = new Observable<EchoMsg>(subscriber => {
135
+ subscriber.next({body: 'Hello world from streaming request.'})
136
+ subscriber.complete()
137
+ })
138
+
139
+ console.log('Calling EchoClientStream: client -> server...')
140
+ result = await demoServiceClient.EchoClientStream(clientRequestStream)
141
+ console.log('success: output', result.body)
124
142
  ```
125
143
 
144
+ ## WebSocket
126
145
 
127
- ### Client
146
+ One way to integrate Go and TypeScript is over a WebSocket:
128
147
 
129
148
  ```typescript
130
- import { WebSocketConn } from '../srpc'
131
- import { EchoerClientImpl } from '../echo/echo'
149
+ import { WebSocketConn } from 'srpc'
150
+ import { EchoerClientImpl } from 'srpc/echo'
132
151
 
133
152
  const ws = new WebSocket('ws://localhost:5000/demo')
134
153
  const channel = new WebSocketConn(ws)
@@ -139,15 +158,6 @@ const result = await demoServiceClient.Echo({
139
158
  body: "Hello world!"
140
159
  })
141
160
  console.log('output', result.body)
142
-
143
- const clientRequestStream = new Observable<EchoMsg>(subscriber => {
144
- subscriber.next({body: 'Hello world from streaming request.'})
145
- subscriber.complete()
146
- })
147
-
148
- console.log('Calling EchoClientStream: client -> server...')
149
- result = await demoServiceClient.EchoClientStream(clientRequestStream)
150
- console.log('success: output', result.body)
151
161
  ```
152
162
 
153
163
  # Attribution
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starpc",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Streaming protobuf RPC service protocol over any two-way channel.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -57,7 +57,7 @@ func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
57
57
  return
58
58
  }
59
59
  go func() {
60
- err := s.srpc.HandleConn(ctx, strm)
60
+ err := s.srpc.HandleStream(ctx, strm)
61
61
  _ = err
62
62
  // TODO: handle / log error?
63
63
  // err != nil && err != io.EOF && err != context.Canceled
@@ -7,12 +7,12 @@ import (
7
7
 
8
8
  // NewServerPipe constructs a open stream func which creates an in-memory Pipe
9
9
  // Stream with the given Server. Starts read pumps for both. Starts the
10
- // HandleConn function on the server in a separate goroutine.
10
+ // HandleStream function on the server in a separate goroutine.
11
11
  func NewServerPipe(server *Server) OpenStreamFunc {
12
12
  return func(ctx context.Context, msgHandler func(pkt *Packet) error) (Writer, error) {
13
13
  srvPipe, clientPipe := net.Pipe()
14
14
  go func() {
15
- _ = server.HandleConn(ctx, srvPipe)
15
+ _ = server.HandleStream(ctx, srvPipe)
16
16
  }()
17
17
  clientPrw := NewPacketReadWriter(clientPipe, msgHandler)
18
18
  go func() {
package/srpc/server.go CHANGED
@@ -3,6 +3,8 @@ package srpc
3
3
  import (
4
4
  "context"
5
5
  "io"
6
+
7
+ "github.com/libp2p/go-libp2p-core/network"
6
8
  )
7
9
 
8
10
  // Server handles incoming RPC streams with a mux.
@@ -18,8 +20,8 @@ func NewServer(mux Mux) *Server {
18
20
  }
19
21
  }
20
22
 
21
- // HandleConn handles an incoming ReadWriteCloser.
22
- func (s *Server) HandleConn(ctx context.Context, rwc io.ReadWriteCloser) error {
23
+ // HandleStream handles an incoming ReadWriteCloser stream.
24
+ func (s *Server) HandleStream(ctx context.Context, rwc io.ReadWriteCloser) error {
23
25
  subCtx, subCtxCancel := context.WithCancel(ctx)
24
26
  defer subCtxCancel()
25
27
  serverRPC := NewServerRPC(subCtx, s.mux)
@@ -27,3 +29,28 @@ func (s *Server) HandleConn(ctx context.Context, rwc io.ReadWriteCloser) error {
27
29
  serverRPC.SetWriter(prw)
28
30
  return prw.ReadPump()
29
31
  }
32
+
33
+ // AcceptMuxedConn runs a loop which calls Accept on a muxer to handle streams.
34
+ //
35
+ // Starts HandleStream in a separate goroutine to handle the stream.
36
+ // Returns context.Canceled or io.EOF when the loop is complete / closed.
37
+ func (s *Server) AcceptMuxedConn(ctx context.Context, mplex network.MuxedConn) error {
38
+ for {
39
+ select {
40
+ case <-ctx.Done():
41
+ return context.Canceled
42
+ default:
43
+ if mplex.IsClosed() {
44
+ return io.EOF
45
+ }
46
+ }
47
+
48
+ muxedStream, err := mplex.AcceptStream()
49
+ if err != nil {
50
+ return err
51
+ }
52
+ go func() {
53
+ _ = s.HandleStream(ctx, muxedStream)
54
+ }()
55
+ }
56
+ }