github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/grpcwrapper/rawtopic/rawtopicreader/rawtopicreader.go (about) 1 package rawtopicreader 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "reflect" 8 9 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Topic" 10 11 "github.com/ydb-platform/ydb-go-sdk/v3/internal/grpcwrapper/rawtopic/rawtopiccommon" 12 "github.com/ydb-platform/ydb-go-sdk/v3/internal/grpcwrapper/rawydb" 13 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" 14 ) 15 16 var ErrUnexpectedMessageType = errors.New("unexpected message type") 17 18 type GrpcStream interface { 19 Send(messageNew *Ydb_Topic.StreamReadMessage_FromClient) error 20 Recv() (*Ydb_Topic.StreamReadMessage_FromServer, error) 21 CloseSend() error 22 } 23 24 type StreamReader struct { 25 Stream GrpcStream 26 } 27 28 func (s StreamReader) CloseSend() error { 29 return s.Stream.CloseSend() 30 } 31 32 //nolint:funlen 33 func (s StreamReader) Recv() (ServerMessage, error) { 34 grpcMess, err := s.Stream.Recv() 35 if xerrors.Is(err, io.EOF) { 36 return nil, err 37 } 38 if err != nil { 39 if !xerrors.IsErrorFromServer(err) { 40 err = xerrors.Transport(err) 41 } 42 43 return nil, err 44 } 45 46 var meta rawtopiccommon.ServerMessageMetadata 47 if err = meta.MetaFromStatusAndIssues(grpcMess); err != nil { 48 return nil, err 49 } 50 if !meta.Status.IsSuccess() { 51 return nil, xerrors.WithStackTrace(fmt.Errorf("ydb: bad status from topic server: %v", meta.Status)) 52 } 53 54 switch m := grpcMess.GetServerMessage().(type) { 55 case *Ydb_Topic.StreamReadMessage_FromServer_InitResponse: 56 resp := &InitResponse{} 57 resp.ServerMessageMetadata = meta 58 resp.fromProto(m.InitResponse) 59 60 return resp, nil 61 case *Ydb_Topic.StreamReadMessage_FromServer_ReadResponse: 62 resp := &ReadResponse{} 63 resp.ServerMessageMetadata = meta 64 if err = resp.fromProto(m.ReadResponse); err != nil { 65 return nil, err 66 } 67 68 return resp, nil 69 case *Ydb_Topic.StreamReadMessage_FromServer_StartPartitionSessionRequest: 70 resp := &StartPartitionSessionRequest{} 71 resp.ServerMessageMetadata = meta 72 if err = resp.fromProto(m.StartPartitionSessionRequest); err != nil { 73 return nil, err 74 } 75 76 return resp, nil 77 case *Ydb_Topic.StreamReadMessage_FromServer_StopPartitionSessionRequest: 78 req := &StopPartitionSessionRequest{} 79 req.ServerMessageMetadata = meta 80 if err = req.fromProto(m.StopPartitionSessionRequest); err != nil { 81 return nil, err 82 } 83 84 return req, nil 85 case *Ydb_Topic.StreamReadMessage_FromServer_CommitOffsetResponse: 86 resp := &CommitOffsetResponse{} 87 resp.ServerMessageMetadata = meta 88 if err = resp.fromProto(m.CommitOffsetResponse); err != nil { 89 return nil, err 90 } 91 92 return resp, nil 93 case *Ydb_Topic.StreamReadMessage_FromServer_PartitionSessionStatusResponse: 94 resp := &PartitionSessionStatusResponse{} 95 resp.ServerMessageMetadata = meta 96 if err = resp.fromProto(m.PartitionSessionStatusResponse); err != nil { 97 return nil, err 98 } 99 100 return resp, nil 101 case *Ydb_Topic.StreamReadMessage_FromServer_UpdateTokenResponse: 102 resp := &UpdateTokenResponse{} 103 resp.ServerMessageMetadata = meta 104 resp.MustFromProto(m.UpdateTokenResponse) 105 106 return resp, nil 107 default: 108 return nil, xerrors.WithStackTrace(fmt.Errorf( 109 "ydb: receive unexpected message (%v): %w", 110 reflect.TypeOf(grpcMess.GetServerMessage()), 111 ErrUnexpectedMessageType, 112 )) 113 } 114 } 115 116 func (s StreamReader) Send(msg ClientMessage) (err error) { 117 defer func() { 118 err = xerrors.Transport(err) 119 }() 120 switch m := msg.(type) { 121 case *InitRequest: 122 grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{ 123 ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_InitRequest{InitRequest: m.toProto()}, 124 } 125 126 return s.Stream.Send(grpcMess) 127 case *ReadRequest: 128 grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{ 129 ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_ReadRequest{ReadRequest: m.toProto()}, 130 } 131 132 return s.Stream.Send(grpcMess) 133 case *StartPartitionSessionResponse: 134 grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{ 135 ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_StartPartitionSessionResponse{ 136 StartPartitionSessionResponse: m.toProto(), 137 }, 138 } 139 140 return s.Stream.Send(grpcMess) 141 case *StopPartitionSessionResponse: 142 grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{ 143 ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_StopPartitionSessionResponse{ 144 StopPartitionSessionResponse: m.toProto(), 145 }, 146 } 147 148 return s.Stream.Send(grpcMess) 149 case *CommitOffsetRequest: 150 grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{ 151 ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_CommitOffsetRequest{ 152 CommitOffsetRequest: m.toProto(), 153 }, 154 } 155 156 return s.Stream.Send(grpcMess) 157 case *PartitionSessionStatusRequest: 158 grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{ 159 ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_PartitionSessionStatusRequest{ 160 PartitionSessionStatusRequest: m.toProto(), 161 }, 162 } 163 164 return s.Stream.Send(grpcMess) 165 case *UpdateTokenRequest: 166 grpcMess := &Ydb_Topic.StreamReadMessage_FromClient{ 167 ClientMessage: &Ydb_Topic.StreamReadMessage_FromClient_UpdateTokenRequest{ 168 UpdateTokenRequest: m.ToProto(), 169 }, 170 } 171 172 return s.Stream.Send(grpcMess) 173 default: 174 return xerrors.WithStackTrace(fmt.Errorf("ydb: send unexpected message type: %v", reflect.TypeOf(msg))) 175 } 176 } 177 178 type ClientMessage interface { 179 isClientMessage() 180 } 181 182 type clientMessageImpl struct{} 183 184 func (*clientMessageImpl) isClientMessage() {} 185 186 type ServerMessage interface { 187 isServerMessage() 188 StatusData() rawtopiccommon.ServerMessageMetadata 189 SetStatus(status rawydb.StatusCode) 190 } 191 192 type serverMessageImpl struct{} 193 194 func (*serverMessageImpl) isServerMessage() {}