github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/topic/topicreadercommon/commit_range.go (about)

     1  package topicreadercommon
     2  
     3  import (
     4  	"sort"
     5  
     6  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/grpcwrapper/rawtopic/rawtopiccommon"
     7  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/grpcwrapper/rawtopic/rawtopicreader"
     8  	"github.com/ydb-platform/ydb-go-sdk/v3/trace"
     9  )
    10  
    11  // PublicCommitRangeGetter return data piece for commit messages range
    12  type PublicCommitRangeGetter interface {
    13  	getCommitRange() PublicCommitRange
    14  }
    15  
    16  type CommitRanges struct {
    17  	Ranges []CommitRange
    18  }
    19  
    20  func (r *CommitRanges) Len() int {
    21  	return len(r.Ranges)
    22  }
    23  
    24  // GetCommitsInfo implements trace.TopicReaderStreamSendCommitMessageStartMessageInfo
    25  func (r *CommitRanges) GetCommitsInfo() []trace.TopicReaderStreamCommitInfo {
    26  	res := make([]trace.TopicReaderStreamCommitInfo, len(r.Ranges))
    27  	for i := range res {
    28  		res[i] = trace.TopicReaderStreamCommitInfo{
    29  			Topic:              r.Ranges[i].PartitionSession.Topic,
    30  			PartitionID:        r.Ranges[i].PartitionSession.PartitionID,
    31  			PartitionSessionID: r.Ranges[i].PartitionSession.StreamPartitionSessionID.ToInt64(),
    32  			StartOffset:        r.Ranges[i].CommitOffsetStart.ToInt64(),
    33  			EndOffset:          r.Ranges[i].CommitOffsetEnd.ToInt64(),
    34  		}
    35  	}
    36  
    37  	return res
    38  }
    39  
    40  func (r *CommitRanges) ToRawMessage() *rawtopicreader.CommitOffsetRequest {
    41  	res := &rawtopicreader.CommitOffsetRequest{}
    42  
    43  	res.CommitOffsets = r.ToPartitionsOffsets()
    44  
    45  	return res
    46  }
    47  
    48  func NewCommitRangesWithCapacity(capacity int) CommitRanges {
    49  	return CommitRanges{Ranges: make([]CommitRange, 0, capacity)}
    50  }
    51  
    52  func NewCommitRangesFromPublicCommits(ranges []PublicCommitRange) CommitRanges {
    53  	res := CommitRanges{}
    54  	res.Ranges = make([]CommitRange, len(ranges))
    55  	for i := 0; i < len(res.Ranges); i++ {
    56  		res.Ranges[i] = ranges[i].priv
    57  	}
    58  
    59  	return res
    60  }
    61  
    62  func (r *CommitRanges) Append(ranges ...PublicCommitRangeGetter) {
    63  	converted := make([]CommitRange, len(ranges))
    64  
    65  	for i := range ranges {
    66  		converted[i] = ranges[i].getCommitRange().priv
    67  		r.Ranges = append(r.Ranges, converted...)
    68  	}
    69  }
    70  
    71  func (r *CommitRanges) AppendMessages(messages ...PublicMessage) {
    72  	converted := make([]CommitRange, len(messages))
    73  
    74  	for i := range messages {
    75  		converted[i] = messages[i].getCommitRange().priv
    76  		r.Ranges = append(r.Ranges, converted...)
    77  	}
    78  }
    79  
    80  func (r *CommitRanges) AppendCommitRange(cr CommitRange) {
    81  	r.Ranges = append(r.Ranges, cr)
    82  }
    83  
    84  func (r *CommitRanges) AppendCommitRanges(ranges []CommitRange) {
    85  	r.Ranges = append(r.Ranges, ranges...)
    86  }
    87  
    88  func (r *CommitRanges) Reset() {
    89  	r.Ranges = r.Ranges[:0]
    90  }
    91  
    92  func (r *CommitRanges) ToPartitionsOffsets() []rawtopicreader.PartitionCommitOffset {
    93  	if len(r.Ranges) == 0 {
    94  		return nil
    95  	}
    96  
    97  	r.Optimize()
    98  
    99  	return r.toRawPartitionCommitOffset()
   100  }
   101  
   102  func (r *CommitRanges) Optimize() {
   103  	if r.Len() == 0 {
   104  		return
   105  	}
   106  
   107  	sort.Slice(r.Ranges, func(i, j int) bool {
   108  		cI, cJ := &r.Ranges[i], &r.Ranges[j]
   109  		switch {
   110  		case cI.PartitionSession.StreamPartitionSessionID < cJ.PartitionSession.StreamPartitionSessionID:
   111  			return true
   112  		case cJ.PartitionSession.StreamPartitionSessionID < cI.PartitionSession.StreamPartitionSessionID:
   113  			return false
   114  		case cI.CommitOffsetStart < cJ.CommitOffsetStart:
   115  			return true
   116  		default:
   117  			return false
   118  		}
   119  	})
   120  
   121  	newCommits := r.Ranges[:1]
   122  	lastCommit := &newCommits[0]
   123  	for i := 1; i < len(r.Ranges); i++ {
   124  		commit := &r.Ranges[i]
   125  		if lastCommit.PartitionSession.StreamPartitionSessionID == commit.PartitionSession.StreamPartitionSessionID &&
   126  			lastCommit.CommitOffsetEnd == commit.CommitOffsetStart {
   127  			lastCommit.CommitOffsetEnd = commit.CommitOffsetEnd
   128  		} else {
   129  			newCommits = append(newCommits, *commit)
   130  			lastCommit = &newCommits[len(newCommits)-1]
   131  		}
   132  	}
   133  
   134  	r.Ranges = newCommits
   135  }
   136  
   137  func (r *CommitRanges) toRawPartitionCommitOffset() []rawtopicreader.PartitionCommitOffset {
   138  	if len(r.Ranges) == 0 {
   139  		return nil
   140  	}
   141  
   142  	newPartition := func(id rawtopicreader.PartitionSessionID) rawtopicreader.PartitionCommitOffset {
   143  		return rawtopicreader.PartitionCommitOffset{
   144  			PartitionSessionID: id,
   145  		}
   146  	}
   147  
   148  	partitionOffsets := make([]rawtopicreader.PartitionCommitOffset, 0, len(r.Ranges))
   149  	partitionOffsets = append(partitionOffsets, newPartition(r.Ranges[0].PartitionSession.StreamPartitionSessionID))
   150  	partition := &partitionOffsets[0]
   151  
   152  	for i := range r.Ranges {
   153  		commit := &r.Ranges[i]
   154  		offsetsRange := rawtopiccommon.OffsetRange{
   155  			Start: commit.CommitOffsetStart,
   156  			End:   commit.CommitOffsetEnd,
   157  		}
   158  		if partition.PartitionSessionID != commit.PartitionSession.StreamPartitionSessionID {
   159  			partitionOffsets = append(partitionOffsets, newPartition(commit.PartitionSession.StreamPartitionSessionID))
   160  			partition = &partitionOffsets[len(partitionOffsets)-1]
   161  		}
   162  		partition.Offsets = append(partition.Offsets, offsetsRange)
   163  	}
   164  
   165  	return partitionOffsets
   166  }
   167  
   168  // PublicCommitRange contains data for commit messages range
   169  //
   170  // Experimental: https://github.com/ydb-platform/ydb-go-sdk/blob/master/VERSIONING.md#experimental
   171  type PublicCommitRange struct {
   172  	priv CommitRange
   173  }
   174  
   175  func (p PublicCommitRange) getCommitRange() PublicCommitRange {
   176  	return p
   177  }
   178  
   179  type CommitRange struct {
   180  	CommitOffsetStart rawtopiccommon.Offset
   181  	CommitOffsetEnd   rawtopiccommon.Offset
   182  	PartitionSession  *PartitionSession
   183  }
   184  
   185  func (c CommitRange) getCommitRange() PublicCommitRange {
   186  	return PublicCommitRange{priv: c}
   187  }
   188  
   189  func (c *CommitRange) session() *PartitionSession {
   190  	return c.PartitionSession
   191  }
   192  
   193  func GetCommitRange(item PublicCommitRangeGetter) CommitRange {
   194  	return item.getCommitRange().priv
   195  }