Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,104 changes: 407 additions & 697 deletions crates/wit-bindgen-go/src/interface.rs

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions crates/wit-bindgen-test/src/go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ impl LanguageMethods for Go {
_args: &[String],
) -> bool {
// The wRPC Go generator does not yet support bare `stream`/`future`
// types, `error-context`, or futures held by resources.
// types, `error-context`, named fixed-length lists, or `map`.
matches!(
name,
"streams.wit"
| "futures.wit"
| "error-context.wit"
| "resources-with-futures.wit"
| "future-same-type-different-names.wit"
| "named-fixed-length-list.wit"
| "map.wit"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func ServeInterface(s wrpc.Server, h Handler) (stop func() error, err error) {
slog.DebugContext(ctx, "calling `wrpc-examples:hello/handler.hello` handler")
r0, err := h.Hello(ctx)
if cErr := r.Close(); cErr != nil {
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:hello/handler", "name", "hello", "err", err)
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:hello/handler", "name", "hello", "err", cErr)
}
if err != nil {
slog.WarnContext(ctx, "failed to handle invocation", "instance", "wrpc-examples:hello/handler", "name", "hello", "err", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func ServeInterface(s wrpc.Server, h Handler) (stop func() error, err error) {
slog.DebugContext(ctx, "calling `wrpc-examples:resources/resources.foo` handler")
r0, err := h.Foo(ctx)
if cErr := r.Close(); cErr != nil {
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:resources/resources", "name", "foo", "err", err)
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:resources/resources", "name", "foo", "err", cErr)
}
if err != nil {
slog.WarnContext(ctx, "failed to handle invocation", "instance", "wrpc-examples:resources/resources", "name", "foo", "err", err)
Expand Down Expand Up @@ -160,7 +160,7 @@ func ServeInterface(s wrpc.Server, h Handler) (stop func() error, err error) {
slog.DebugContext(ctx, "calling `wrpc-examples:resources/resources.foo.baz` handler")
r0, err := h.Foo_Baz(ctx, p0)
if cErr := r.Close(); cErr != nil {
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:resources/resources", "name", "foo.baz", "err", err)
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:resources/resources", "name", "foo.baz", "err", cErr)
}
if err != nil {
slog.WarnContext(ctx, "failed to handle invocation", "instance", "wrpc-examples:resources/resources", "name", "foo.baz", "err", err)
Expand Down Expand Up @@ -279,7 +279,7 @@ func ServeInterface(s wrpc.Server, h Handler) (stop func() error, err error) {
slog.DebugContext(ctx, "calling `wrpc-examples:resources/resources.foo.bar` handler")
r0, err := h.Foo_Bar(ctx, p0)
if cErr := r.Close(); cErr != nil {
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:resources/resources", "name", "foo.bar", "err", err)
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:resources/resources", "name", "foo.bar", "err", cErr)
}
if err != nil {
slog.WarnContext(ctx, "failed to handle invocation", "instance", "wrpc-examples:resources/resources", "name", "foo.bar", "err", err)
Expand Down Expand Up @@ -398,7 +398,7 @@ func ServeInterface(s wrpc.Server, h Handler) (stop func() error, err error) {
slog.DebugContext(ctx, "calling `wrpc-examples:resources/resources.bar` handler")
r0, err := h.Bar(ctx, p0)
if cErr := r.Close(); cErr != nil {
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:resources/resources", "name", "bar", "err", err)
slog.ErrorContext(ctx, "failed to close reader", "instance", "wrpc-examples:resources/resources", "name", "bar", "err", cErr)
}
if err != nil {
slog.WarnContext(ctx, "failed to handle invocation", "instance", "wrpc-examples:resources/resources", "name", "bar", "err", err)
Expand Down
89 changes: 18 additions & 71 deletions examples/go/streams-client/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package app
import (
"context"
"fmt"
"io"
"log/slog"
"os"
"sync"
Expand All @@ -26,57 +25,24 @@ func init() {
})))
}

type ThrottleStream[T any] struct {
tick *time.Ticker
values []T
}

func (s *ThrottleStream[T]) Receive() ([]T, error) {
if len(s.values) == 0 {
return nil, io.EOF
}
<-s.tick.C
var v T
v, s.values = s.values[0], s.values[1:]
return []T{v}, nil
}

func (s *ThrottleStream[T]) Close() error {
s.tick.Stop()
return nil
}

type ThrottleReader struct {
tick *time.Ticker
buf []byte
}

func (s *ThrottleReader) Read(p []byte) (int, error) {
if len(s.buf) == 0 {
return 0, io.EOF
}
<-s.tick.C
var b byte
b, s.buf = s.buf[0], s.buf[1:]
p[0] = b
return 1, nil
}

func (s *ThrottleReader) Close() error {
s.tick.Stop()
return nil
func throttle[T any](values []T, d time.Duration) <-chan []T {
ch := make(chan []T)
go func() {
defer close(ch)
tick := time.NewTicker(d)
defer tick.Stop()
for _, v := range values {
<-tick.C
ch <- []T{v}
}
}()
return ch
}

func Run(prefix string, client wrpc.Invoker) error {
numbers, bytes, errCh, err := handler.Echo(context.Background(), client, &handler.Req{
Numbers: &ThrottleStream[uint64]{
tick: time.NewTicker(time.Second),
values: []uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
},
Bytes: &ThrottleReader{
tick: time.NewTicker(time.Second),
buf: []byte("foo bar baz"),
},
Numbers: throttle([]uint64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, time.Second),
Bytes: throttle([]byte("foo bar baz"), time.Second),
})
if err != nil {
return fmt.Errorf("failed to call `wrpc-examples:streams/handler.echo`: %w", err)
Expand All @@ -87,38 +53,19 @@ func Run(prefix string, client wrpc.Invoker) error {
wg.Add(1)
go func() {
defer wg.Done()
defer numbers.Close()
for {
chunk, err := numbers.Receive()
if err == io.EOF {
return
}
if err != nil {
slog.Error("failed to receive number chunk", "err", err)
return
}
for chunk := range numbers {
fmt.Printf("%s numbers: %v\n", prefix, chunk)
}
}()
wg.Add(1)
go func() {
defer wg.Done()
defer bytes.Close()
var chunk [128]byte
for {
n, err := bytes.Read(chunk[:])
if err == io.EOF {
return
}
if err != nil {
slog.Error("failed to receive byte chunk", "err", err)
return
}
fmt.Printf("%s bytes: %s\n", prefix, chunk[:n])
for chunk := range bytes {
fmt.Printf("%s bytes: %s\n", prefix, chunk)
}
}()
for err := range errCh {
slog.Error("failed to transmit async parameters", "err", err)
slog.Error("failed to exchange async values", "err", err)
}
return nil
}
Loading
Loading