internal/jsonrpc2_v2: an updated jsonrpc2 library
Change-Id: I609173baa6842d33068a7e9596d54f03d89c5401 Reviewed-on: https://go-review.googlesource.com/c/tools/+/292169 Run-TryBot: Ian Cottrell <iancottrell@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Ian Cottrell <iancottrell@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
8d98c809a2
commit
cf8963447b
1 changed files with 1992 additions and 0 deletions
84
internal/jsonrpc2/jsonrpc2.go
Normal file
84
internal/jsonrpc2/jsonrpc2.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2018 The Go MCP SDK Authors. All rights reserved.
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec.
|
||||
// https://www.jsonrpc.org/specification
|
||||
// It is intended to be compatible with other implementations at the wire level.
|
||||
package jsonrpc2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrIdleTimeout is returned when serving timed out waiting for new connections.
|
||||
ErrIdleTimeout = errors.New("timed out waiting for new connections")
|
||||
// ErrNotHandled is returned from a handler to indicate it did not handle the
|
||||
// message.
|
||||
ErrNotHandled = errors.New("JSON RPC not handled")
|
||||
// ErrAsyncResponse is returned from a handler to indicate it will generate a
|
||||
// response asynchronously.
|
||||
ErrAsyncResponse = errors.New("JSON RPC asynchronous response")
|
||||
)
|
||||
|
||||
// Preempter handles messages on a connection before they are queued to the main
|
||||
// handler.
|
||||
// Primarily this is used for cancel handlers or notifications for which out of
|
||||
// order processing is not an issue.
|
||||
type Preempter interface {
|
||||
// Preempt is invoked for each incoming request before it is queued.
|
||||
// If the request is a call, it must return a value or an error for the reply.
|
||||
// Preempt should not block or start any new messages on the connection.
|
||||
Preempt(ctx context.Context, req *Request) (interface{}, error)
|
||||
}
|
||||
|
||||
// Handler handles messages on a connection.
|
||||
type Handler interface {
|
||||
// Handle is invoked for each incoming request.
|
||||
// If the request is a call, it must return a value or an error for the reply.
|
||||
Handle(ctx context.Context, req *Request) (interface{}, error)
|
||||
}
|
||||
|
||||
type defaultHandler struct{}
|
||||
|
||||
func (defaultHandler) Preempt(context.Context, *Request) (interface{}, error) {
|
||||
return nil, ErrNotHandled
|
||||
}
|
||||
|
||||
func (defaultHandler) Handle(context.Context, *Request) (interface{}, error) {
|
||||
return nil, ErrNotHandled
|
||||
}
|
||||
|
||||
// async is a small helper for things with an asynchronous result that you can
|
||||
// wait for.
|
||||
type async struct {
|
||||
ready chan struct{}
|
||||
errBox chan error
|
||||
}
|
||||
|
||||
func (a *async) init() {
|
||||
a.ready = make(chan struct{})
|
||||
a.errBox = make(chan error, 1)
|
||||
a.errBox <- nil
|
||||
}
|
||||
|
||||
func (a *async) done() {
|
||||
close(a.ready)
|
||||
}
|
||||
|
||||
func (a *async) wait() error {
|
||||
<-a.ready
|
||||
err := <-a.errBox
|
||||
a.errBox <- err
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *async) setError(err error) {
|
||||
storedErr := <-a.errBox
|
||||
if storedErr == nil {
|
||||
storedErr = err
|
||||
}
|
||||
a.errBox <- storedErr
|
||||
}
|
||||
Loading…
Reference in a new issue