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

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