@@ -31,8 +31,9 @@ import (
3131// the stream on a retryable error.
3232type pullStream struct {
3333 ctx context.Context
34- open func () (pb.Subscriber_StreamingPullClient , error )
35- cancel context.CancelFunc
34+ cancel context.CancelFunc // cancel function of the context above
35+ open func () (pb.Subscriber_StreamingPullClient , context.CancelFunc , error )
36+ close context.CancelFunc // cancel function to close down the currently open stream
3637
3738 mu sync.Mutex
3839 spc * pb.Subscriber_StreamingPullClient
@@ -50,8 +51,9 @@ func newPullStream(ctx context.Context, streamingPull streamingPullFunc, subName
5051 return & pullStream {
5152 ctx : ctx ,
5253 cancel : cancel ,
53- open : func () (pb.Subscriber_StreamingPullClient , error ) {
54- spc , err := streamingPull (ctx , gax .WithGRPCOptions (grpc .MaxCallRecvMsgSize (maxSendRecvBytes )))
54+ open : func () (pb.Subscriber_StreamingPullClient , context.CancelFunc , error ) {
55+ sctx , close := context .WithCancel (ctx )
56+ spc , err := streamingPull (sctx , gax .WithGRPCOptions (grpc .MaxCallRecvMsgSize (maxSendRecvBytes )))
5557 if err == nil {
5658 recordStat (ctx , StreamRequestCount , 1 )
5759 streamAckDeadline := int32 (maxDurationPerLeaseExtension / time .Second )
@@ -69,9 +71,10 @@ func newPullStream(ctx context.Context, streamingPull streamingPullFunc, subName
6971 })
7072 }
7173 if err != nil {
72- return nil , err
74+ close ()
75+ return nil , nil , err
7376 }
74- return spc , nil
77+ return spc , close , nil
7578 },
7679 }
7780}
@@ -100,29 +103,33 @@ func (s *pullStream) get(spc *pb.Subscriber_StreamingPullClient) (*pb.Subscriber
100103 if spc != s .spc {
101104 return s .spc , nil
102105 }
106+ // we are about to open a new stream: if necessary, make sure the previous one is closed
107+ if s .close != nil {
108+ s .close ()
109+ }
103110 // Either this is the very first call on this stream (s.spc == nil), or we have a valid
104111 // retry request. Either way, open a new stream.
105112 // The lock is held here for a long time, but it doesn't matter because no callers could get
106113 // anything done anyway.
107114 s .spc = new (pb.Subscriber_StreamingPullClient )
108- * s .spc , s .err = s .openWithRetry () // Any error from openWithRetry is permanent.
115+ * s .spc , s .close , s . err = s .openWithRetry () // Any error from openWithRetry is permanent.
109116 return s .spc , s .err
110117}
111118
112- func (s * pullStream ) openWithRetry () (pb.Subscriber_StreamingPullClient , error ) {
119+ func (s * pullStream ) openWithRetry () (pb.Subscriber_StreamingPullClient , context. CancelFunc , error ) {
113120 r := defaultRetryer {}
114121 for {
115122 recordStat (s .ctx , StreamOpenCount , 1 )
116- spc , err := s .open ()
123+ spc , close , err := s .open ()
117124 bo , shouldRetry := r .Retry (err )
118125 if err != nil && shouldRetry {
119126 recordStat (s .ctx , StreamRetryCount , 1 )
120127 if err := gax .Sleep (s .ctx , bo ); err != nil {
121- return nil , err
128+ return nil , nil , err
122129 }
123130 continue
124131 }
125- return spc , err
132+ return spc , close , err
126133 }
127134}
128135
0 commit comments