github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/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 // A PreempterFunc implements the Preempter interface for a standalone Preempt function. 51 type PreempterFunc func(ctx context.Context, req *Request) (interface{}, error) 52 53 func (f PreempterFunc) Preempt(ctx context.Context, req *Request) (interface{}, error) { 54 return f(ctx, req) 55 } 56 57 var _ Preempter = PreempterFunc(nil) 58 59 // Handler handles messages on a connection. 60 type Handler interface { 61 // Handle is invoked sequentially for each incoming request that has not 62 // already been handled by a Preempter. 63 // 64 // If the Request has a nil ID, Handle must return a nil result, 65 // and any error may be logged but will not be reported to the caller. 66 // 67 // If the Request has a non-nil ID, Handle must return either a 68 // non-nil, JSON-marshalable result, or a non-nil error. 69 // 70 // The Context passed to Handle will be canceled if the 71 // connection is broken or the request is canceled or completed. 72 // (If Handle returns ErrAsyncResponse, ctx will remain uncanceled 73 // until either Cancel or Respond is called for the request's ID.) 74 Handle(ctx context.Context, req *Request) (result interface{}, err error) 75 } 76 77 type defaultHandler struct{} 78 79 func (defaultHandler) Preempt(context.Context, *Request) (interface{}, error) { 80 return nil, ErrNotHandled 81 } 82 83 func (defaultHandler) Handle(context.Context, *Request) (interface{}, error) { 84 return nil, ErrNotHandled 85 } 86 87 // A HandlerFunc implements the Handler interface for a standalone Handle function. 88 type HandlerFunc func(ctx context.Context, req *Request) (interface{}, error) 89 90 func (f HandlerFunc) Handle(ctx context.Context, req *Request) (interface{}, error) { 91 return f(ctx, req) 92 } 93 94 var _ Handler = HandlerFunc(nil) 95 96 // async is a small helper for operations with an asynchronous result that you 97 // can wait for. 98 type async struct { 99 ready chan struct{} // closed when done 100 firstErr chan error // 1-buffered; contains either nil or the first non-nil error 101 } 102 103 func newAsync() *async { 104 var a async 105 a.ready = make(chan struct{}) 106 a.firstErr = make(chan error, 1) 107 a.firstErr <- nil 108 return &a 109 } 110 111 func (a *async) done() { 112 close(a.ready) 113 } 114 115 func (a *async) isDone() bool { 116 select { 117 case <-a.ready: 118 return true 119 default: 120 return false 121 } 122 } 123 124 func (a *async) wait() error { 125 <-a.ready 126 err := <-a.firstErr 127 a.firstErr <- err 128 return err 129 } 130 131 func (a *async) setError(err error) { 132 storedErr := <-a.firstErr 133 if storedErr == nil { 134 storedErr = err 135 } 136 a.firstErr <- storedErr 137 }