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