github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/internal/grpcwrapper/rawtopic/rawtopicwriter/messages.go (about) 1 package rawtopicwriter 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "time" 8 9 "github.com/ydb-platform/ydb-go-genproto/protos/Ydb_Topic" 10 "google.golang.org/protobuf/types/known/timestamppb" 11 12 "github.com/ydb-platform/ydb-go-sdk/v3/internal/grpcwrapper/rawtopic/rawtopiccommon" 13 "github.com/ydb-platform/ydb-go-sdk/v3/internal/xerrors" 14 ) 15 16 var ( 17 errWriteResultProtoIsNil = xerrors.Wrap(errors.New("ydb: write result proto is nil")) 18 errWriteResultResponseWriteAckIsNil = xerrors.Wrap(errors.New("ydb: write result response write ack is nil")) 19 errWriteResultResponseStatisticIsNil = xerrors.Wrap(errors.New("ydb: write result response statistic is nil")) 20 ) 21 22 type InitRequest struct { 23 clientMessageImpl 24 25 Path string 26 ProducerID string 27 WriteSessionMeta map[string]string 28 29 Partitioning Partitioning 30 31 GetLastSeqNo bool 32 } 33 34 func (r *InitRequest) toProto() (*Ydb_Topic.StreamWriteMessage_InitRequest, error) { 35 res := &Ydb_Topic.StreamWriteMessage_InitRequest{ 36 Path: r.Path, 37 ProducerId: r.ProducerID, 38 WriteSessionMeta: r.WriteSessionMeta, 39 GetLastSeqNo: r.GetLastSeqNo, 40 } 41 42 err := r.Partitioning.setToProtoInitRequest(res) 43 if err != nil { 44 return nil, err 45 } 46 47 return res, nil 48 } 49 50 // Partitioning is struct because it included in per-message structure and 51 // places on hot-path for write messages 52 // structure will work and compile-optimization better then interface 53 type Partitioning struct { 54 Type PartitioningType 55 MessageGroupID string 56 PartitionID int64 57 } 58 59 func NewPartitioningMessageGroup(messageGroupID string) Partitioning { 60 return Partitioning{ 61 Type: PartitioningMessageGroupID, 62 MessageGroupID: messageGroupID, 63 } 64 } 65 66 func NewPartitioningPartitionID(partitionID int64) Partitioning { 67 return Partitioning{ 68 Type: PartitioningPartitionID, 69 PartitionID: partitionID, 70 } 71 } 72 73 func (p *Partitioning) setToProtoInitRequest(r *Ydb_Topic.StreamWriteMessage_InitRequest) error { 74 switch p.Type { 75 case PartitioningUndefined: 76 r.Partitioning = nil 77 case PartitioningMessageGroupID: 78 r.Partitioning = &Ydb_Topic.StreamWriteMessage_InitRequest_MessageGroupId{ 79 MessageGroupId: p.MessageGroupID, 80 } 81 case PartitioningPartitionID: 82 r.Partitioning = &Ydb_Topic.StreamWriteMessage_InitRequest_PartitionId{ 83 PartitionId: p.PartitionID, 84 } 85 default: 86 return xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf( 87 "ydb: unexpected partition type while set to init request: %v", 88 p.Type, 89 ))) 90 } 91 92 return nil 93 } 94 95 func (p *Partitioning) setToProtoMessage(m *Ydb_Topic.StreamWriteMessage_WriteRequest_MessageData) error { 96 switch p.Type { 97 case PartitioningUndefined: 98 m.Partitioning = nil 99 case PartitioningMessageGroupID: 100 m.Partitioning = &Ydb_Topic.StreamWriteMessage_WriteRequest_MessageData_MessageGroupId{ 101 MessageGroupId: p.MessageGroupID, 102 } 103 case PartitioningPartitionID: 104 m.Partitioning = &Ydb_Topic.StreamWriteMessage_WriteRequest_MessageData_PartitionId{ 105 PartitionId: p.PartitionID, 106 } 107 default: 108 return xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf( 109 "ydb: unexpected partition type while set to message proto: %v", 110 p.Type, 111 ))) 112 } 113 114 return nil 115 } 116 117 type PartitioningType int 118 119 const ( 120 PartitioningUndefined PartitioningType = iota 121 PartitioningMessageGroupID 122 PartitioningPartitionID 123 ) 124 125 type InitResult struct { 126 serverMessageImpl 127 rawtopiccommon.ServerMessageMetadata 128 129 LastSeqNo int64 130 SessionID string 131 PartitionID int64 132 SupportedCodecs rawtopiccommon.SupportedCodecs 133 } 134 135 func (r *InitResult) mustFromProto(response *Ydb_Topic.StreamWriteMessage_InitResponse) { 136 r.SessionID = response.GetSessionId() 137 r.PartitionID = response.GetPartitionId() 138 r.LastSeqNo = response.GetLastSeqNo() 139 r.SupportedCodecs.MustFromProto(response.GetSupportedCodecs()) 140 } 141 142 type WriteRequest struct { 143 clientMessageImpl 144 145 Messages []MessageData 146 Codec rawtopiccommon.Codec 147 } 148 149 func (r *WriteRequest) toProto() (p *Ydb_Topic.StreamWriteMessage_FromClient_WriteRequest, err error) { 150 messages := make([]*Ydb_Topic.StreamWriteMessage_WriteRequest_MessageData, len(r.Messages)) 151 152 for i := range r.Messages { 153 messages[i], err = r.Messages[i].ToProto() 154 if err != nil { 155 return nil, err 156 } 157 } 158 159 res := &Ydb_Topic.StreamWriteMessage_FromClient_WriteRequest{ 160 WriteRequest: &Ydb_Topic.StreamWriteMessage_WriteRequest{ 161 Messages: messages, 162 Codec: int32(r.Codec.ToProto()), 163 }, 164 } 165 166 return res, nil 167 } 168 169 type MessageData struct { 170 SeqNo int64 171 CreatedAt time.Time 172 UncompressedSize int64 173 Partitioning Partitioning 174 MetadataItems []rawtopiccommon.MetadataItem 175 Data []byte 176 } 177 178 func (d *MessageData) ToProto() (*Ydb_Topic.StreamWriteMessage_WriteRequest_MessageData, error) { 179 res := &Ydb_Topic.StreamWriteMessage_WriteRequest_MessageData{ 180 SeqNo: d.SeqNo, 181 CreatedAt: timestamppb.New(d.CreatedAt), 182 Data: d.Data, 183 UncompressedSize: d.UncompressedSize, 184 } 185 err := d.Partitioning.setToProtoMessage(res) 186 if err != nil { 187 return nil, err 188 } 189 190 for i := range d.MetadataItems { 191 res.MetadataItems = append(res.GetMetadataItems(), &Ydb_Topic.MetadataItem{ 192 Key: d.MetadataItems[i].Key, 193 Value: d.MetadataItems[i].Value, 194 }) 195 } 196 197 return res, nil 198 } 199 200 type WriteResult struct { 201 serverMessageImpl 202 rawtopiccommon.ServerMessageMetadata 203 204 Acks []WriteAck 205 PartitionID int64 206 WriteStatistics WriteStatistics 207 } 208 209 func (r *WriteResult) fromProto(response *Ydb_Topic.StreamWriteMessage_WriteResponse) error { 210 if response == nil { 211 return xerrors.WithStackTrace(errWriteResultProtoIsNil) 212 } 213 r.Acks = make([]WriteAck, len(response.GetAcks())) 214 for i := range response.GetAcks() { 215 if err := r.Acks[i].fromProto(response.GetAcks()[i]); err != nil { 216 return err 217 } 218 } 219 r.PartitionID = response.GetPartitionId() 220 221 return r.WriteStatistics.fromProto(response.GetWriteStatistics()) 222 } 223 224 type WriteAck struct { 225 SeqNo int64 226 MessageWriteStatus MessageWriteStatus 227 } 228 229 func (wa *WriteAck) fromProto(pb *Ydb_Topic.StreamWriteMessage_WriteResponse_WriteAck) error { 230 if pb == nil { 231 return xerrors.WithStackTrace(errWriteResultResponseWriteAckIsNil) 232 } 233 wa.SeqNo = pb.GetSeqNo() 234 235 return wa.MessageWriteStatus.fromProto(pb.GetMessageWriteStatus()) 236 } 237 238 // MessageWriteStatus is struct because it included in per-message structure and 239 // places on hot-path for write messages 240 // structure will work and compile-optimization better then interface 241 type MessageWriteStatus struct { 242 Type WriteStatusType 243 WrittenOffset int64 244 SkippedReason WriteStatusSkipReason 245 } 246 247 func (s *MessageWriteStatus) fromProto(status interface{}) error { 248 switch v := status.(type) { 249 case *Ydb_Topic.StreamWriteMessage_WriteResponse_WriteAck_Written_: 250 s.Type = WriteStatusTypeWritten 251 s.WrittenOffset = v.Written.GetOffset() 252 253 return nil 254 case *Ydb_Topic.StreamWriteMessage_WriteResponse_WriteAck_Skipped_: 255 s.Type = WriteStatusTypeSkipped 256 s.SkippedReason = WriteStatusSkipReason(v.Skipped.GetReason()) 257 258 return nil 259 default: 260 return xerrors.WithStackTrace(xerrors.Wrap(fmt.Errorf("ydb: unexpected write status type: %v", reflect.TypeOf(v)))) 261 } 262 } 263 264 type WriteStatusType int 265 266 const ( 267 WriteStatusTypeUnknown WriteStatusType = iota 268 WriteStatusTypeWritten 269 WriteStatusTypeSkipped 270 ) 271 272 type WriteStatusSkipReason int 273 274 const ( 275 WriteStatusSkipReasonUnspecified = WriteStatusSkipReason(Ydb_Topic.StreamWriteMessage_WriteResponse_WriteAck_Skipped_REASON_UNSPECIFIED) //nolint:lll 276 WriteStatusSkipReasonAlreadyWritten = WriteStatusSkipReason(Ydb_Topic.StreamWriteMessage_WriteResponse_WriteAck_Skipped_REASON_ALREADY_WRITTEN) //nolint:lll 277 ) 278 279 type WriteStatistics struct { 280 PersistingTime time.Duration 281 MinQueueWaitTime time.Duration 282 MaxQueueWaitTime time.Duration 283 TopicQuotaWaitTime time.Duration 284 } 285 286 func (s *WriteStatistics) fromProto(statistics *Ydb_Topic.StreamWriteMessage_WriteResponse_WriteStatistics) error { 287 if statistics == nil { 288 return xerrors.WithStackTrace(errWriteResultResponseStatisticIsNil) 289 } 290 291 s.PersistingTime = statistics.GetPersistingTime().AsDuration() 292 s.MinQueueWaitTime = statistics.GetMinQueueWaitTime().AsDuration() 293 s.MaxQueueWaitTime = statistics.GetMaxQueueWaitTime().AsDuration() 294 s.TopicQuotaWaitTime = statistics.GetTopicQuotaWaitTime().AsDuration() 295 296 return nil 297 } 298 299 type UpdateTokenRequest struct { 300 clientMessageImpl 301 302 rawtopiccommon.UpdateTokenRequest 303 } 304 305 type UpdateTokenResponse struct { 306 rawtopiccommon.UpdateTokenResponse 307 308 serverMessageImpl 309 310 rawtopiccommon.ServerMessageMetadata 311 }