github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/client/grpc/stream.go (about) 1 // Copyright 2020 Asim Aslam 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Original source: github.com/micro/go-micro/v3/client/grpc/stream.go 16 17 package grpc 18 19 import ( 20 "context" 21 "io" 22 "sync" 23 24 "github.com/tickoalcantara12/micro/v3/service/client" 25 "google.golang.org/grpc" 26 ) 27 28 // Implements the streamer interface 29 type grpcStream struct { 30 // embed so we can access if need be 31 grpc.ClientStream 32 33 sync.RWMutex 34 closed bool 35 err error 36 conn *poolConn 37 request client.Request 38 response client.Response 39 context context.Context 40 close func(err error) 41 } 42 43 func (g *grpcStream) Context() context.Context { 44 return g.context 45 } 46 47 func (g *grpcStream) Request() client.Request { 48 return g.request 49 } 50 51 func (g *grpcStream) Response() client.Response { 52 return g.response 53 } 54 55 func (g *grpcStream) Send(msg interface{}) error { 56 if err := g.ClientStream.SendMsg(msg); err != nil { 57 g.setError(err) 58 return err 59 } 60 return nil 61 } 62 63 func (g *grpcStream) Recv(msg interface{}) (err error) { 64 defer g.setError(err) 65 66 if err = g.ClientStream.RecvMsg(msg); err != nil { 67 // #202 - inconsistent gRPC stream behavior 68 // the only way to tell if the stream is done is when we get a EOF on the Recv 69 // here we should close the underlying gRPC ClientConn 70 closeErr := g.Close() 71 if err == io.EOF && closeErr != nil { 72 err = closeErr 73 } 74 75 return err 76 } 77 78 return 79 } 80 81 func (g *grpcStream) Error() error { 82 g.RLock() 83 defer g.RUnlock() 84 return g.err 85 } 86 87 func (g *grpcStream) setError(e error) { 88 g.Lock() 89 g.err = e 90 g.Unlock() 91 } 92 93 // Close the gRPC send stream 94 // #202 - inconsistent gRPC stream behavior 95 // The underlying gRPC stream should not be closed here since the 96 // stream should still be able to receive after this function call 97 // TODO: should the conn be closed in another way? 98 func (g *grpcStream) Close() error { 99 g.Lock() 100 defer g.Unlock() 101 102 if g.closed { 103 return nil 104 } 105 106 // close the connection 107 g.closed = true 108 g.close(g.err) 109 return g.ClientStream.CloseSend() 110 }