1
0
Fork 0
mirror of https://github.com/sourcegraph/jsonrpc2.git synced 2026-06-16 04:04:56 +02:00

transparently simplify control flow (#83)

This commit is contained in:
Kevin Gillette 2025-02-17 07:55:54 -07:00 committed by GitHub
parent 534fd43609
commit 2cc94179e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 72 additions and 89 deletions

105
conn.go
View file

@ -187,15 +187,17 @@ func (c *Conn) close(cause error) error {
}
func (c *Conn) readMessages(ctx context.Context) {
var err error
for err == nil {
for {
var m anyMessage
err = c.stream.ReadObject(&m)
err := c.stream.ReadObject(&m)
if err != nil {
break
c.close(err)
return
}
switch {
// TODO: handle the case where both request and response are nil.
case m.request != nil:
for _, onRecv := range c.onRecv {
onRecv(m.request, nil)
@ -204,43 +206,36 @@ func (c *Conn) readMessages(ctx context.Context) {
case m.response != nil:
resp := m.response
if resp != nil {
id := resp.ID
c.mu.Lock()
call := c.pending[id]
delete(c.pending, id)
c.mu.Unlock()
id := resp.ID
c.mu.Lock()
call := c.pending[id]
delete(c.pending, id)
c.mu.Unlock()
if call != nil {
call.response = resp
}
if len(c.onRecv) > 0 {
var req *Request
if call != nil {
req = call.request
}
for _, onRecv := range c.onRecv {
onRecv(req, resp)
}
}
switch {
case call == nil:
c.logger.Printf("jsonrpc2: ignoring response #%s with no corresponding request\n", id)
case resp.Error != nil:
call.done <- resp.Error
close(call.done)
default:
call.done <- nil
close(call.done)
}
var req *Request
if call != nil {
call.response = resp
req = call.request
}
for _, onRecv := range c.onRecv {
onRecv(req, resp)
}
if call == nil {
c.logger.Printf("jsonrpc2: ignoring response #%s with no corresponding request\n", id)
continue
}
var err error
if resp.Error != nil {
err = resp.Error
}
call.done <- err
close(call.done)
}
}
c.close(err)
}
func (c *Conn) send(_ context.Context, m *anyMessage, wait bool) (cc *call, err error) {
@ -339,25 +334,20 @@ type Waiter struct {
// error is returned.
func (w Waiter) Wait(ctx context.Context, result interface{}) error {
select {
case err, ok := <-w.call.done:
if !ok {
err = ErrClosed
}
if err != nil {
return err
}
if result != nil {
if w.call.response.Result == nil {
w.call.response.Result = &jsonNull
}
if err := json.Unmarshal(*w.call.response.Result, result); err != nil {
return err
}
}
return nil
case <-ctx.Done():
return ctx.Err()
case err, ok := <-w.call.done:
if !ok {
return ErrClosed
}
if err != nil || result == nil {
return err
}
if w.call.response.Result == nil {
w.call.response.Result = &jsonNull
}
return json.Unmarshal(*w.call.response.Result, result)
}
}
@ -423,12 +413,7 @@ func (m *anyMessage) UnmarshalJSON(data []byte) error {
return errors.New("jsonrpc2: invalid empty batch")
}
for i := range msgs {
if err := checkType(&msg{
ID: msgs[i].ID,
Method: msgs[i].Method,
Result: msgs[i].Result,
Error: msgs[i].Error,
}); err != nil {
if err := checkType(&msgs[i]); err != nil {
return err
}
}