github.com/micro/go-micro/v2@v2.9.1/server/rpc_stream.go (about)

     1  package server
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"io"
     7  	"sync"
     8  
     9  	"github.com/micro/go-micro/v2/codec"
    10  )
    11  
    12  // Implements the Streamer interface
    13  type rpcStream struct {
    14  	sync.RWMutex
    15  	id      string
    16  	closed  bool
    17  	err     error
    18  	request Request
    19  	codec   codec.Codec
    20  	context context.Context
    21  }
    22  
    23  func (r *rpcStream) Context() context.Context {
    24  	return r.context
    25  }
    26  
    27  func (r *rpcStream) Request() Request {
    28  	return r.request
    29  }
    30  
    31  func (r *rpcStream) Send(msg interface{}) error {
    32  	r.Lock()
    33  	defer r.Unlock()
    34  
    35  	resp := codec.Message{
    36  		Target:   r.request.Service(),
    37  		Method:   r.request.Method(),
    38  		Endpoint: r.request.Endpoint(),
    39  		Id:       r.id,
    40  		Type:     codec.Response,
    41  	}
    42  
    43  	if err := r.codec.Write(&resp, msg); err != nil {
    44  		r.err = err
    45  	}
    46  
    47  	return nil
    48  }
    49  
    50  func (r *rpcStream) Recv(msg interface{}) error {
    51  	req := new(codec.Message)
    52  	req.Type = codec.Request
    53  
    54  	err := r.codec.ReadHeader(req, req.Type)
    55  	r.Lock()
    56  	defer r.Unlock()
    57  	if err != nil {
    58  		// discard body
    59  		r.codec.ReadBody(nil)
    60  		r.err = err
    61  		return err
    62  	}
    63  
    64  	// check the error
    65  	if len(req.Error) > 0 {
    66  		// Check the client closed the stream
    67  		switch req.Error {
    68  		case lastStreamResponseError.Error():
    69  			// discard body
    70  			r.Unlock()
    71  			r.codec.ReadBody(nil)
    72  			r.Lock()
    73  			r.err = io.EOF
    74  			return io.EOF
    75  		default:
    76  			return errors.New(req.Error)
    77  		}
    78  	}
    79  
    80  	// we need to stay up to date with sequence numbers
    81  	r.id = req.Id
    82  	r.Unlock()
    83  	err = r.codec.ReadBody(msg)
    84  	r.Lock()
    85  	if err != nil {
    86  		r.err = err
    87  		return err
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  func (r *rpcStream) Error() error {
    94  	r.RLock()
    95  	defer r.RUnlock()
    96  	return r.err
    97  }
    98  
    99  func (r *rpcStream) Close() error {
   100  	r.Lock()
   101  	defer r.Unlock()
   102  	r.closed = true
   103  	return r.codec.Close()
   104  }