-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DBZ-8163 Add inherit epoch feature #208
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* | ||
* Copyright Debezium Authors. | ||
* | ||
* Licensed under the Apache Software License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 | ||
*/ | ||
|
||
package io.debezium.connector.vitess.pipeline.txmetadata; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* Class used to determine which parents a shard range descended from. Used to set the epoch to the succeediing | ||
* epoch of its parents. | ||
*/ | ||
public class ShardLineage { | ||
|
||
/** | ||
* Return the epoch value of the shard, based on its parents epochs. | ||
* If there are parents present, return the max of the parent epochs plus one. | ||
* If there are no parents present, it returns zero. | ||
* | ||
* @param shardString The descendant shard to find parents of | ||
* @param shardEpochMap The map to search for parents | ||
* @return The epoch value of the descendant shard | ||
*/ | ||
public static Long getInheritedEpoch(String shardString, ShardEpochMap shardEpochMap) { | ||
Shard shard = new Shard(shardString); | ||
|
||
Long maxParentEpoch = -1L; | ||
for (Map.Entry<String, Long> shardEpoch : shardEpochMap.getMap().entrySet()) { | ||
String currentShardString = shardEpoch.getKey(); | ||
Long currentEpoch = shardEpoch.getValue(); | ||
Shard currentShard = new Shard(currentShardString); | ||
if (shard.overlaps(currentShard)) { | ||
maxParentEpoch = Math.max(maxParentEpoch, currentEpoch); | ||
} | ||
} | ||
|
||
return maxParentEpoch + 1; | ||
} | ||
|
||
private static class Shard { | ||
|
||
// A string lexicographically less than all other strings | ||
public static final String NEGATIVE_INFINITY = ""; | ||
// A string lexicographically greater than all other strings | ||
public static final String POSITIVE_INFINITY = "\uFFFF"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is 4F long/big enough, do we need 8F? or have an assert if we sees the upper bound is more than 4 characters long. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah this |
||
|
||
private final String lowerBound; | ||
private final String upperBound; | ||
|
||
Shard(String shard) { | ||
String[] shardInterval = getShardInterval(shard.toLowerCase()); | ||
this.lowerBound = getLowerBound(shardInterval); | ||
this.upperBound = getUpperBound(shardInterval); | ||
validateBounds(); | ||
} | ||
|
||
private void validateBounds() { | ||
if (this.lowerBound.compareTo(this.upperBound) >= 0) { | ||
throw new IllegalArgumentException("Invalid shard range " + this); | ||
} | ||
} | ||
|
||
public boolean overlaps(Shard shard) { | ||
return this.lowerBound.compareTo(shard.upperBound) < 0 && this.upperBound.compareTo(shard.lowerBound) > 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about the situation when the two ranges meet on the boundary ( == 0 case)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Vitess ranges are have inclusive lower bounds and exclusive upper bounds so this should be correct (docs). We can think about each part:
I added a test to demonstrate this case. |
||
} | ||
|
||
private static String getLowerBound(String[] shardInterval) { | ||
if (shardInterval.length < 1 || shardInterval[0].isEmpty()) { | ||
return NEGATIVE_INFINITY; | ||
} | ||
return shardInterval[0]; | ||
} | ||
|
||
private static String getUpperBound(String[] shardInterval) { | ||
if (shardInterval.length != 2 || shardInterval[1].isEmpty()) { | ||
return POSITIVE_INFINITY; | ||
} | ||
return shardInterval[1]; | ||
} | ||
|
||
private static String[] getShardInterval(String shard) { | ||
return shard.split("-"); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Shard{" + | ||
"lowerBound=" + lowerBound + | ||
", upperBound=" + upperBound + | ||
"}"; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.