-
Notifications
You must be signed in to change notification settings - Fork 751
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
[GOBBLIN-1901] Define MultiActiveLeaseArbiter Decorator to Model Failed Lease Completion #3765
base: master
Are you sure you want to change the base?
Conversation
|
||
/** | ||
* Given a host name return an optional containing the InetAddress object if one can be constructed for the input | ||
* // TODO: provide details about expected hostName format |
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.
may be no need to stipulate, given the type
... perhaps rename the function to getInetAddressForHostName
?
@@ -103,6 +103,11 @@ public class ConfigurationKeys { | |||
public static final String DEFAULT_SCHEDULER_LEASE_DETERMINATION_STORE_DB_TABLE = "gobblin_scheduler_lease_determination_store"; | |||
// Refers to the event we originally tried to acquire a lease which achieved `consensus` among participants through | |||
// the database | |||
public static final String MULTI_ACTIVE_LEASE_ARBITER_HOST_TO_BIT_MASK_MAP = MYSQL_LEASE_ARBITER_PREFIX + ".hostToBitMaskMap"; |
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.
since this is not interpreted by the MysqlMALeaseArbiter
, it shouldn't borrow that class's config prefix. let's make a prefix just for the class reading this config. (that will clue in config maintainers that it's unnecessary once the class itself is no longer being used.)
* host. If the bitwise AND comparison to the host bit mask equals the bitmask we fail the call. | ||
*/ | ||
@Slf4j | ||
public class MysqlMultiActiveLeaseArbiterTestingDecorator extends MysqlMultiActiveLeaseArbiter { |
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.
the name TestingDecorator
suggests nothing about behavior. Decorator seems a relevant pattern, and suggests reusability, but it's more important to name how/why it decorates than to state vaguely that decoration is afoot.
how about FailureInjectingMALeaseArbiter
or FailureInjectingMALeaseArbiterDecorator
?
Also, on the subject of reuse, why base this specifically on MysqlMALeaseArbiter
, rather the MALeaseArbiter
interface/base class? as currently written, this is not truly a decorator, but rather an extension to MysqlMALA
. (in java a decorator would implement an interface, but almost never extend a concrete derived class that already implements it.)
to be a decorator, the ctor should either take a MALeaseArbiter
instance to delegate to or else create one internally. here, I suggest the latter, which means this class (itself named within config) should itself read its own (prefixed) config to learn the class name it should internally create an instance of.
public class MysqlMultiActiveLeaseArbiterTestingDecorator extends MysqlMultiActiveLeaseArbiter { | ||
private final int bitMaskLength; | ||
private final int numHosts; | ||
private final HashMap<Integer, Integer> hostIdToBitMask = new HashMap(); |
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.
shouldn't there be only one MALA instance per host? if so, it shouldn't need to worry about any host bitmask but its own, so probably an Optional<Integer>
.
@@ -103,6 +103,11 @@ public class ConfigurationKeys { | |||
public static final String DEFAULT_SCHEDULER_LEASE_DETERMINATION_STORE_DB_TABLE = "gobblin_scheduler_lease_determination_store"; | |||
// Refers to the event we originally tried to acquire a lease which achieved `consensus` among participants through | |||
// the database | |||
public static final String MULTI_ACTIVE_LEASE_ARBITER_HOST_TO_BIT_MASK_MAP = MYSQL_LEASE_ARBITER_PREFIX + ".hostToBitMaskMap"; | |||
public static final String MULTI_ACTIVE_LEASE_ARBITER_BIT_MASK_LENGTH = MYSQL_LEASE_ARBITER_PREFIX + ".bitMaskLength"; |
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.
usually BIT_MASK
is one word, so BITMASK
and bitmask
/** | ||
* Retrieve the host id as a number between 1 through `numHosts` by using the host address's hashcode. | ||
* @return | ||
*/ | ||
protected int getHostIdFromAddress(InetAddress address) { | ||
return (address.hashCode() % numHosts) + 1; | ||
} |
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.
I don't understand the concept of host ID... please explain.
I'd imagine each host would be identified by its specific hostname and the configured bitmask it should use keyed by that name
* @param bitmask 4-bit binary integer used to compare against modified lease acquisition timestamp | ||
* @return true if the host should fail the lease completion attempt | ||
*/ | ||
protected static boolean shouldFailLeaseCompletionAttempt(LeaseObtainedStatus status, int bitmask, |
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.
likely should be @VisibleForTesting
protected static boolean shouldFailLeaseCompletionAttempt(LeaseObtainedStatus status, int bitmask, | ||
int bitMaskLength) { | ||
// Convert event timestamp to binary | ||
Long.toString(status.getLeaseAcquisitionTimestamp()).getBytes(); |
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.
remove this (since not assigned)
String scatteredBinaryString = scatterBinaryStringBits(binaryString); | ||
// Take last `bitMaskLength`` bits of the string | ||
int length = scatteredBinaryString.length(); | ||
String shortenedBinaryString = scatteredBinaryString.substring(length-bitMaskLength, length); |
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.
let's do binary entirely with numbers (no strings). e.g.:
boolean shouldFail = (scatterTimestamp(ts) & bitmaskBits) != 0
* success with the following methodology. We take the binary representation of the lease obtained timestamp, scatter | ||
* its bits through bit interleaving of the first and second halves of the binary representation to differentiate | ||
* behavior of consecutive timestamps, and compare the last N digits (determined through config) to the bit mask of the |
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.
I really like the idea of scattering (to avoid long runs of on/off). while I have very little background in number theory, the idea of interleaving high-order with low-order bits intuitively concerns me... so not sure if I'm missing something.
here's my logic: when representing millis as a java long, we can essentially consider the high-order bits to be constants, since the lowest of the long's high bits [32:63] only changes once every 10^9 secs. after interleaving, wouldn't odd position bits nearly never change, while even-positions would. the assignment:
host0:0001,host1:0010,host2:0100,host3:1000
would give drastically different probability for host1
and host3
, than for host0
, and host2
--right?
instead I suggest bit "scattering" by passing the number through a hash digest, like MD5 or SHA1
Dear Gobblin maintainers,
Please accept this PR. I understand that it will not be reviewed until I have checked off all the steps below!
JIRA
Description
Creates MysqlMultiActiveLeaseAribterTestingDecorator class used to model scenarios where a lease owner fails to complete a lease successfully intermittently (representing a variety of slowness or failure cases that can result on the participant side, network connectivity, or database).
It will fail on calls to {@link MysqlMultiActiveLeaseArbiter.recordLeaseSuccess()} where a deterministic function of the lease obtained timestamp matches a bitmask of the host. Ideally, each participant should fail on different calls (with limited overlap if we want to test that). See java doc for more details.
Tests
WIP (will add in second iteration once methodology is agreed upon)
Commits