Browse Source

Use single channel for api responses

main
Sam Hofius 2 years ago
parent
commit
4801d34f6e
  1. 47
      chat.go

47
chat.go

@ -12,12 +12,23 @@ import ( @@ -12,12 +12,23 @@ import (
type ChatAPI struct {
sync.Mutex
toStdin chan []byte
fromStdout chan []byte
fromStdout chan msg
fromListen chan []byte
errors chan error
kbLoc string
}
type msg interface{}
type apiMsg []byte
type errMsg struct {
Err error
}
func (e errMsg) Error() string {
return e.Err.Error()
}
func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
if opts.ChannelBufferSize <= 0 {
opts.ChannelBufferSize = 10
@ -26,9 +37,8 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) { @@ -26,9 +37,8 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
// set up the channels
api = &ChatAPI{
toStdin: make(chan []byte, opts.ChannelBufferSize),
fromStdout: make(chan []byte, opts.ChannelBufferSize),
fromStdout: make(chan msg, opts.ChannelBufferSize),
fromListen: make(chan []byte, opts.ChannelBufferSize),
errors: make(chan error, opts.ChannelBufferSize),
}
// get the basics
@ -75,7 +85,7 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) { @@ -75,7 +85,7 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
case msg := <-api.toStdin:
_, err := chatApi.Stdin().Write(msg)
if err != nil {
api.errors <- err
api.fromStdout <- errMsg{Err: err}
}
case <-ctx.Done():
return
@ -97,7 +107,7 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) { @@ -97,7 +107,7 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
cr := ctxreader.NewContextReader(ctx, chatApi.Stderr())
scanner := bufio.NewScanner(cr)
for scanner.Scan() {
api.errors <- fmt.Errorf("%v", scanner.Text())
api.fromStdout <- errMsg{Err: fmt.Errorf("%v", scanner.Text())}
}
}()
@ -114,14 +124,27 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) { @@ -114,14 +124,27 @@ func NewChatAPI(ctx context.Context, opts Options) (api *ChatAPI, err error) {
return
}
func (c *ChatAPI) SendRaw(msg []byte) ([]byte, error) {
func (c *ChatAPI) SendRaw(ctx context.Context, msg []byte) ([]byte, error) {
c.Lock()
defer c.Unlock()
// send message to api
c.toStdin <- msg
select {
case resp := <-c.fromStdout:
return resp, nil
case err := <-c.errors:
return nil, err
// wait for response
for {
select {
case resp := <-c.fromStdout:
switch resp := resp.(type) {
case apiMsg:
return resp, nil
case errMsg:
return nil, resp.Err
}
case <-ctx.Done():
return nil, ctx.Err()
default:
// still waiting, do nothing
}
}
}

Loading…
Cancel
Save