@@ -15,11 +15,19 @@ import (
15
15
var (
16
16
// ErrIdleTimeout is returned when serving timed out waiting for new connections.
17
17
ErrIdleTimeout = errors .New ("timed out waiting for new connections" )
18
- // ErrNotHandled is returned from a handler to indicate it did not handle the
19
- // message.
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.
20
24
ErrNotHandled = errors .New ("JSON RPC not handled" )
25
+
21
26
// ErrAsyncResponse is returned from a handler to indicate it will generate a
22
27
// response asynchronously.
28
+ //
29
+ // ErrAsyncResponse must not be returned for notifications,
30
+ // which do not receive responses.
23
31
ErrAsyncResponse = errors .New ("JSON RPC asynchronous response" )
24
32
)
25
33
@@ -28,17 +36,33 @@ var (
28
36
// Primarily this is used for cancel handlers or notifications for which out of
29
37
// order processing is not an issue.
30
38
type Preempter interface {
31
- // Preempt is invoked for each incoming request before it is queued.
32
- // If the request is a call, it must return a value or an error for the reply.
33
- // Preempt should not block or start any new messages on the connection.
34
- Preempt (ctx context.Context , req * Request ) (interface {}, error )
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 )
35
48
}
36
49
37
50
// Handler handles messages on a connection.
38
51
type Handler interface {
39
- // Handle is invoked for each incoming request.
40
- // If the request is a call, it must return a value or an error for the reply.
41
- Handle (ctx context.Context , req * Request ) (interface {}, error )
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 )
42
66
}
43
67
44
68
type defaultHandler struct {}
@@ -60,15 +84,15 @@ func (f HandlerFunc) Handle(ctx context.Context, req *Request) (interface{}, err
60
84
// async is a small helper for operations with an asynchronous result that you
61
85
// can wait for.
62
86
type async struct {
63
- ready chan struct {} // signals that the operation has completed
64
- errBox chan error // guards the operation result
87
+ ready chan struct {} // closed when done
88
+ firstErr chan error // 1-buffered; contains either nil or the first non-nil error
65
89
}
66
90
67
91
func newAsync () * async {
68
92
var a async
69
93
a .ready = make (chan struct {})
70
- a .errBox = make (chan error , 1 )
71
- a .errBox <- nil
94
+ a .firstErr = make (chan error , 1 )
95
+ a .firstErr <- nil
72
96
return & a
73
97
}
74
98
@@ -87,15 +111,15 @@ func (a *async) isDone() bool {
87
111
88
112
func (a * async ) wait () error {
89
113
<- a .ready
90
- err := <- a .errBox
91
- a .errBox <- err
114
+ err := <- a .firstErr
115
+ a .firstErr <- err
92
116
return err
93
117
}
94
118
95
119
func (a * async ) setError (err error ) {
96
- storedErr := <- a .errBox
120
+ storedErr := <- a .firstErr
97
121
if storedErr == nil {
98
122
storedErr = err
99
123
}
100
- a .errBox <- storedErr
124
+ a .firstErr <- storedErr
101
125
}
0 commit comments