Skip to content

Commit

Permalink
js: avoid blocking the event loop
Browse files Browse the repository at this point in the history
...by using spsc, an unbounded queue, instead of a channel for messages.

This makes use of spsc's .Close() method, introduced in
capnproto/go-capnp#449
  • Loading branch information
zenhack committed Feb 11, 2023
1 parent cb32f4d commit a1172ca
Showing 1 changed file with 8 additions and 6 deletions.
14 changes: 8 additions & 6 deletions js/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@
package js

import (
"context"
"syscall/js"

"capnproto.org/go/capnp/v3"
"capnproto.org/go/capnp/v3/exp/spsc"
"capnproto.org/go/capnp/v3/rpc/transport"
)

var _ transport.Codec = &Conn{}

type Conn struct {
value js.Value
msgs chan *capnp.Message
msgs spsc.Queue[*capnp.Message]
ready chan struct{}
err error
}
Expand Down Expand Up @@ -45,7 +47,7 @@ func New(url string, subprotocols []string) *Conn {
value.Set("binaryType", "arraybuffer")
ret := &Conn{
value: value,
msgs: make(chan *capnp.Message),
msgs: spsc.New[*capnp.Message](),
ready: make(chan struct{}),
}
ret.value.Call("addEventListener", "message",
Expand All @@ -59,17 +61,17 @@ func New(url string, subprotocols []string) *Conn {
js.CopyBytesToGo(buf, data)
msg, err := capnp.Unmarshal(buf)
if err != nil {
close(ret.msgs)
ret.err = err
ret.msgs.Close()
return nil
}
ret.msgs <- msg
ret.msgs.Send(msg)
return nil
}))
ret.value.Call("addEventListener", "error",
js.FuncOf(func(this js.Value, args []js.Value) any {
ret.err = websocketError{event: args[0]}
close(ret.msgs)
ret.msgs.Close()
return nil
}))
ret.value.Call("addEventListener", "open",
Expand All @@ -96,7 +98,7 @@ func (c *Conn) Encode(msg *capnp.Message) error {
}

func (c *Conn) Decode() (*capnp.Message, error) {
msg := <-c.msgs
msg, _ := c.msgs.Recv(context.Background())
return msg, c.err
}

Expand Down

0 comments on commit a1172ca

Please sign in to comment.