github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/internal/jsonrpc2_v2/jsonrpc2.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec.
     6  // https://www.jsonrpc.org/specification
     7  // It is intended to be compatible with other implementations at the wire level.
     8  package jsonrpc2
     9  
    10  import (
    11  	"context"
    12  	"errors"
    13  )
    14  
    15  var (
    16  	// ErrIdleTimeout is returned when serving timed out waiting for new connections.
    17  	ErrIdleTimeout = errors.New("timed out waiting for new connections")
    18  
    19  	// ErrNotHandled is returned from a Handler or Preempter to indicate it did
    20  	// not handle the request.
    21  	//
    22  	// If a Handler returns ErrNotHandled, the server replies with
    23  	// ErrMethodNotFound.
    24  	ErrNotHandled = errors.New("JSON RPC not handled")
    25  
    26  	// ErrAsyncResponse is returned from a handler to indicate it will generate a
    27  	// response asynchronously.
    28  	//
    29  	// ErrAsyncResponse must not be returned for notifications,
    30  	// which do not receive responses.
    31  	ErrAsyncResponse = errors.New("JSON RPC asynchronous response")
    32  )
    33  
    34  // Preempter handles messages on a connection before they are queued to the main
    35  // handler.
    36  // Primarily this is used for cancel handlers or notifications for which out of
    37  // order processing is not an issue.
    38  type Preempter interface {
    39  	// Preempt is invoked for each incoming request before it is queued for handling.
    40  	//
    41  	// If Preempt returns ErrNotHandled, the request will be queued,
    42  	// and eventually passed to a Handle call.
    43  	//
    44  	// Otherwise, the result and error are processed as if returned by Handle.
    45  	//
    46  	// Preempt must not block. (The Context passed to it is for Values only.)
    47  	Preempt(ctx context.Context, req *Request) (result interface{}, err error)
    48  }
    49  
    50  // Handler handles messages on a connection.
    51  type Handler interface {
    52  	// Handle is invoked sequentially for each incoming request that has not
    53  	// already been handled by a Preempter.
    54  	//
    55  	// If the Request has a nil ID, Handle must return a nil result,
    56  	// and any error may be logged but will not be reported to the caller.
    57  	//
    58  	// If the Request has a non-nil ID, Handle must return either a
    59  	// non-nil, JSON-marshalable result, or a non-nil error.
    60  	//
    61  	// The Context passed to Handle will be canceled if the
    62  	// connection is broken or the request is canceled or completed.
    63  	// (If Handle returns ErrAsyncResponse, ctx will remain uncanceled
    64  	// until either Cancel or Respond is called for the request's ID.)
    65  	Handle(ctx context.Context, req *Request) (result interface{}, err error)
    66  }
    67  
    68  type defaultHandler struct{}
    69  
    70  func (defaultHandler) Preempt(context.Context, *Request) (interface{}, error) {
    71  	return nil, ErrNotHandled
    72  }
    73  
    74  func (defaultHandler) Handle(context.Context, *Request) (interface{}, error) {
    75  	return nil, ErrNotHandled
    76  }
    77  
    78  type HandlerFunc func(ctx context.Context, req *Request) (interface{}, error)
    79  
    80  func (f HandlerFunc) Handle(ctx context.Context, req *Request) (interface{}, error) {
    81  	return f(ctx, req)
    82  }
    83  
    84  // async is a small helper for operations with an asynchronous result that you
    85  // can wait for.
    86  type async struct {
    87  	ready    chan struct{} // closed when done
    88  	firstErr chan error    // 1-buffered; contains either nil or the first non-nil error
    89  }
    90  
    91  func newAsync() *async {
    92  	var a async
    93  	a.ready = make(chan struct{})
    94  	a.firstErr = make(chan error, 1)
    95  	a.firstErr <- nil
    96  	return &a
    97  }
    98  
    99  func (a *async) done() {
   100  	close(a.ready)
   101  }
   102  
   103  func (a *async) isDone() bool {
   104  	select {
   105  	case <-a.ready:
   106  		return true
   107  	default:
   108  		return false
   109  	}
   110  }
   111  
   112  func (a *async) wait() error {
   113  	<-a.ready
   114  	err := <-a.firstErr
   115  	a.firstErr <- err
   116  	return err
   117  }
   118  
   119  func (a *async) setError(err error) {
   120  	storedErr := <-a.firstErr
   121  	if storedErr == nil {
   122  		storedErr = err
   123  	}
   124  	a.firstErr <- storedErr
   125  }