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 }