Skip to content

Commit

Permalink
add godocs.
Browse files Browse the repository at this point in the history
  • Loading branch information
raulk authored and Stebalien committed Jul 20, 2021
1 parent cd4571f commit 8413c08
Showing 1 changed file with 20 additions and 12 deletions.
32 changes: 20 additions & 12 deletions lib/rpcenc/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,32 +78,38 @@ func ReaderParamEncoder(addr string) jsonrpc.Option {
})
}

type waitReadCloser struct {
// watchReadCloser watches the ReadCloser and closes the watch channel when
// either: (1) the ReaderCloser fails on Read (including with a benign error
// like EOF), or (2) when Close is called.
//
// Use it be notified of terminal states, in situations where a Read failure (or
// EOF) is considered a terminal state too (besides Close).
type watchReadCloser struct {
io.ReadCloser
wait chan struct{}
watch chan struct{}
closeOnce sync.Once
}

func (w *waitReadCloser) Read(p []byte) (int, error) {
func (w *watchReadCloser) Read(p []byte) (int, error) {
n, err := w.ReadCloser.Read(p)
if err != nil {
w.closeOnce.Do(func() {
close(w.wait)
close(w.watch)
})
}
return n, err
}

func (w *waitReadCloser) Close() error {
func (w *watchReadCloser) Close() error {
w.closeOnce.Do(func() {
close(w.wait)
close(w.watch)
})
return w.ReadCloser.Close()
}

func ReaderParamDecoder() (http.HandlerFunc, jsonrpc.ServerOption) {
var readersLk sync.Mutex
readers := map[uuid.UUID]chan *waitReadCloser{}
readers := map[uuid.UUID]chan *watchReadCloser{}

hnd := func(resp http.ResponseWriter, req *http.Request) {
strId := path.Base(req.URL.Path)
Expand All @@ -116,14 +122,14 @@ func ReaderParamDecoder() (http.HandlerFunc, jsonrpc.ServerOption) {
readersLk.Lock()
ch, found := readers[u]
if !found {
ch = make(chan *waitReadCloser)
ch = make(chan *watchReadCloser)
readers[u] = ch
}
readersLk.Unlock()

wr := &waitReadCloser{
wr := &watchReadCloser{
ReadCloser: req.Body,
wait: make(chan struct{}),
watch: make(chan struct{}),
}

tctx, cancel := context.WithTimeout(req.Context(), Timeout)
Expand All @@ -139,7 +145,9 @@ func ReaderParamDecoder() (http.HandlerFunc, jsonrpc.ServerOption) {
}

select {
case <-wr.wait:
case <-wr.watch:
// TODO should we check if we failed the Read, and if so
// return an HTTP 500? i.e. turn watch into a chan error?
case <-req.Context().Done():
log.Errorf("context error in reader stream handler (2): %v", req.Context().Err())
resp.WriteHeader(500)
Expand Down Expand Up @@ -172,7 +180,7 @@ func ReaderParamDecoder() (http.HandlerFunc, jsonrpc.ServerOption) {
readersLk.Lock()
ch, found := readers[u]
if !found {
ch = make(chan *waitReadCloser)
ch = make(chan *watchReadCloser)
readers[u] = ch
}
readersLk.Unlock()
Expand Down

0 comments on commit 8413c08

Please sign in to comment.