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 }