Merge pull request #10019 from thrawn01/grpc-proxy-watch-errors

Improve watch error reporting when using grpc proxy
This commit is contained in:
Xiang Li 2018-09-10 12:54:33 -07:00 committed by GitHub
commit ec5ff10436
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 8 deletions

View File

@ -16,6 +16,7 @@ package clientv3
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"sync" "sync"
"time" "time"
@ -333,7 +334,7 @@ func (w *watcher) Watch(ctx context.Context, key string, opts ...OpOption) Watch
case <-wr.ctx.Done(): case <-wr.ctx.Done():
case <-donec: case <-donec:
if wgs.closeErr != nil { if wgs.closeErr != nil {
closeCh <- WatchResponse{closeErr: wgs.closeErr} closeCh <- WatchResponse{Canceled: true, closeErr: wgs.closeErr}
break break
} }
// retry; may have dropped stream from no ctxs // retry; may have dropped stream from no ctxs
@ -348,7 +349,7 @@ func (w *watcher) Watch(ctx context.Context, key string, opts ...OpOption) Watch
case <-ctx.Done(): case <-ctx.Done():
case <-donec: case <-donec:
if wgs.closeErr != nil { if wgs.closeErr != nil {
closeCh <- WatchResponse{closeErr: wgs.closeErr} closeCh <- WatchResponse{Canceled: true, closeErr: wgs.closeErr}
break break
} }
// retry; may have dropped stream from no ctxs // retry; may have dropped stream from no ctxs
@ -432,6 +433,7 @@ func (w *watcher) closeStream(wgs *watchGrpcStream) {
func (w *watchGrpcStream) addSubstream(resp *pb.WatchResponse, ws *watcherStream) { func (w *watchGrpcStream) addSubstream(resp *pb.WatchResponse, ws *watcherStream) {
// check watch ID for backward compatibility (<= v3.3) // check watch ID for backward compatibility (<= v3.3)
if resp.WatchId == -1 || (resp.Canceled && resp.CancelReason != "") { if resp.WatchId == -1 || (resp.Canceled && resp.CancelReason != "") {
w.closeErr = v3rpc.Error(errors.New(resp.CancelReason))
// failed; no channel // failed; no channel
close(ws.recvc) close(ws.recvc)
return return
@ -457,7 +459,7 @@ func (w *watchGrpcStream) closeSubstream(ws *watcherStream) {
} }
// close subscriber's channel // close subscriber's channel
if closeErr := w.closeErr; closeErr != nil && ws.initReq.ctx.Err() == nil { if closeErr := w.closeErr; closeErr != nil && ws.initReq.ctx.Err() == nil {
go w.sendCloseSubstream(ws, &WatchResponse{closeErr: w.closeErr}) go w.sendCloseSubstream(ws, &WatchResponse{Canceled: true, closeErr: w.closeErr})
} else if ws.outc != nil { } else if ws.outc != nil {
close(ws.outc) close(ws.outc)
} }

View File

@ -229,11 +229,14 @@ func (wps *watchProxyStream) recvLoop() error {
case *pb.WatchRequest_CreateRequest: case *pb.WatchRequest_CreateRequest:
cr := uv.CreateRequest cr := uv.CreateRequest
if err = wps.checkPermissionForWatch(cr.Key, cr.RangeEnd); err != nil && err == rpctypes.ErrPermissionDenied { if err := wps.checkPermissionForWatch(cr.Key, cr.RangeEnd); err != nil {
// Return WatchResponse which is caused by permission checking if and only if wps.watchCh <- &pb.WatchResponse{
// the error is permission denied. For other errors (e.g. timeout or connection closed), Header: &pb.ResponseHeader{},
// the permission checking mechanism should do nothing for preserving error code. WatchId: -1,
wps.watchCh <- &pb.WatchResponse{Header: &pb.ResponseHeader{}, WatchId: -1, Created: true, Canceled: true} Created: true,
Canceled: true,
CancelReason: err.Error(),
}
continue continue
} }