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  }