Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/hsfzxjy/go-srpc
Simple streaming RPC for Golang.
https://github.com/hsfzxjy/go-srpc
Last synced: 18 days ago
JSON representation
Simple streaming RPC for Golang.
- Host: GitHub
- URL: https://github.com/hsfzxjy/go-srpc
- Owner: hsfzxjy
- License: apache-2.0
- Created: 2022-06-03T06:24:35.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2022-08-21T08:58:18.000Z (over 2 years ago)
- Last Synced: 2024-06-20T22:32:27.426Z (6 months ago)
- Language: Go
- Size: 46.9 KB
- Stars: 18
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# go-srpc
A package that implements streaming RPC in Go, with highlights as:
- **No Dependancy** `srpc` merely extends the built-in `net/rpc`.
- **Ease of Use** `srpc` supports pushing versatile events to the client, including ordinary values or logging entries.
- **Server-side Timeout Control** Server is able to disconnect a stream after client being silent for a certain while.
- **Client-side Cancellation** Client is able to cancel an ongoing stream.An example for quick glance:
```go
package mainimport (
"errors"
"log"
"net"
"net/http"
"net/rpc"
"time""github.com/hsfzxjy/go-srpc"
)type Foo int
func (*Foo) Bar(n int, s *srpc.Session) error {
return srpc.S(func() error {
for i := 0; i < n; i++ {
s.PushValue(i)
s.Logf("Log from Server: i=%d\n", i)
}
return errors.New("example error")
}, s, nil)
}func main() {
// start RPC server
rpc.Register(new(Foo))
rpc.HandleHTTP()
listener, _ := net.Listen("tcp", ":1234")
go http.Serve(listener, nil)time.Sleep(time.Millisecond * 10)
// prepare RPC client
cl, _ := rpc.DialHTTP("tcp", "localhost:1234")
cli := srpc.WrapClient(cl)// invoke remote stream function
h, _ := cli.CallStream("Foo.Bar", 6)
// enumerate the result
for x := range h.C() {
log.Printf("recieve value from remote: %+v\n", x)
}
// check potential returned error
if err := h.Result(); err != nil {
log.Printf("remote returns error: %+v", err)
}listener.Close()
}
```## Usage
### Server-side
To define a streaming method that would continuously push events to the client, one should use the following snippet
```go
import "github.com/hsfzxjy/srpc"func (*Foo) Bar(arg ArgType, s *srpc.Session) error {
return srpc.S(func() error {
// your code goes here// push arbitary values to the client
s.PushValue(42)
s.PushValue("Hello world")// log something at the client-side
s.Logf("Log from server! The arg is %v", arg)// wait for a client-side interrupt
<-s.EndedC()
// which may caused by
switch s.EndCause {
case srpc.EC_CLIENT_CANCELED:
// a cancellation
case srpc.EC_CLIENT_TIMEOUT:
// a client timeout
}// return an optional error to the client
return nil
}, s, nil)
```The third argument of `srpc.S` can be used to configure the current session
```go
srpc.S(func() error { ... }, s, &SessionConfig {
// The capacity of pushing channel.
// PushValue() or Logf() will block if client does not recieve in-time.
// Default: 10
BufferCapacity: 0,
// Timeout control for lazy clients.
// If PushValue() or Logf() block for duration `ClientTimeout`,
// they panic and abort the whole stream.
// Default: 10 * time.Second
ClientTimeout: 1 * time.Second,
// Keep the session alive up to duration `KeepAlive` after it finished,
// so that client is able to recieve remaining events.
// Default: 10 * time.Second
KeepAlive: 1 * time.Second,
})
```### Client
To call a streaming method at remote, one should firstly wraps an existing `rpc.Client`, for example
```go
cl, _ := rpc.DialHTTP("tcp", "localhost:1234")
cli := srpc.WrapClient(cl)
````cli.CallStream()` allows you to invoke a remote streaming method
```go
h, err := cli.CallStream("Foo.Bar", arg)
````err` would be non-nil if the method does not exist. With `h`, you may recieve values, perform cancellation or inspect potential errors from remote
```go
// recieve values
<- h.C()
for x := h.C() {
println(x)
}// cancel the stream and no consequent events will be pushed
h.Cancel()// inspect potential error
var err error = h.Err
// inspect potential panic
var p any = h.Panic
// or simply use h.Result()
// if remote panics, h.Result() will panic with the same value
err := h.Result()
```Check [examples/](./examples/) for more concrete examples.
# [License](./LICENSE)
The Apache License Version 2.0