Class ManagedLeaderLatch
- All Implemented Interfaces:
io.dropwizard.lifecycle.Managed
LeaderLatch which standardizes the id and latch path in ZooKeeper, and which
registers with Dropwizard so that it manages the lifecycle (mainly to ensure the latch is stopped when the
Dropwizard app stops).- Implementation Note:
- Any methods that use
hasLeadership()may result in aManagedLeaderLatchExceptionsince that method can potentially throw one. See its documentation for the possible situations in which an exception could be thrown.
-
Constructor Summary
ConstructorsConstructorDescriptionManagedLeaderLatch(org.apache.curator.framework.CuratorFramework client, String id, String serviceName, org.apache.curator.framework.recipes.leader.LeaderLatchListener... listeners) Construct a latch with a specific ID and standard latch path.ManagedLeaderLatch(org.apache.curator.framework.CuratorFramework client, ServiceDescriptor serviceDescriptor, org.apache.curator.framework.recipes.leader.LeaderLatchListener... listeners) Construct a latch with a standard ID and latch path. -
Method Summary
Modifier and TypeMethodDescriptionChecks whether this instance is the leader, returning aLeadershipStatusobject that callers can use to act upon.booleanThis method is the negation ofhasLeadership().getId()org.apache.curator.framework.recipes.leader.LeaderLatch.StateGet the current latch state.org.apache.curator.framework.recipes.leader.ParticipantGet the leader of this latch.org.apache.curator.framework.recipes.leader.LeaderLatchAn "escape hatch" to get theLeaderLatchmanaged by this object.Collection<org.apache.curator.framework.recipes.leader.Participant>Get the participants (i.e., Dropwizard services) in this latch.booleanReturns whether this instance is the leader, or throws aManagedLeaderLatchExceptionif Curator is not started yet or has been closed; this latch is not started yet or has been closed; or if there are no latch participants yet.booleanReturns whether this instance is the leader, or false if there are any errors getting leadership status.booleanisClosed()Check if the latch is closed.booleanCheck if the latch is started.static StringleaderLatchId(String serviceName, String serviceVersion, String hostname, int port) Utility method to generate a standard latch id for a service.static StringleaderLatchId(ServiceDescriptor serviceDescriptor) Utility method to generate a standard latch id for a service.static StringleaderLatchPath(String serviceName) Utility method to generate a standard latch path for a service.voidstart()Starts the latch, possibly creating non-existent znodes in ZooKeeper first.voidstop()Stops the latch.toString()voidwhenLeader(Runnable action) Perform the givenactionsynchronously only if this latch is currently the leader.<T> Optional<T>whenLeader(Supplier<T> resultSupplier) Perform the given action defined byresultSuppliersynchronously only if this latch is currently the leader, returning the result ofresultSupplier.whenLeaderAsync(Runnable action) Perform the givenactionasynchronously only if this latch is currently the leader.<T> Optional<CompletableFuture<T>>whenLeaderAsync(Supplier<T> resultSupplier) Perform the given action defined byresultSupplierasynchronously only if this latch is currently the leader, returning aCompletableFuturewhose result will be the result of theresultSupplier.<T> Optional<CompletableFuture<T>>whenLeaderAsync(Supplier<T> resultSupplier, Executor executor) Same aswhenLeaderAsync(Supplier)but uses suppliedexecutorinstead ofCompletableFuture's default executor.
-
Constructor Details
-
ManagedLeaderLatch
public ManagedLeaderLatch(org.apache.curator.framework.CuratorFramework client, ServiceDescriptor serviceDescriptor, org.apache.curator.framework.recipes.leader.LeaderLatchListener... listeners) Construct a latch with a standard ID and latch path.- Parameters:
client- theCuratorFrameworkclient that this latch should useserviceDescriptor- service metadatalisteners- zero or moreLeaderLatchListenerinstances to attach to the leader latch- Throws:
IllegalArgumentException- if any arguments are null or blank
-
ManagedLeaderLatch
public ManagedLeaderLatch(org.apache.curator.framework.CuratorFramework client, String id, String serviceName, org.apache.curator.framework.recipes.leader.LeaderLatchListener... listeners) Construct a latch with a specific ID and standard latch path.The
serviceNameshould be the generic name of a service, e.g. "payment-service" or "order-service", instead of a unique service identifier.- Parameters:
client- theCuratorFrameworkclient that this latch should useid- the unique ID for this latch instanceserviceName- the generic name of the service, which ensures the same latch path is used for all instances of a given servicelisteners- zero or moreLeaderLatchListenerinstances to attach to the leader latch- Throws:
IllegalArgumentException- if any arguments are null or blank- See Also:
-
-
Method Details
-
leaderLatchId
Utility method to generate a standard latch id for a service.- Parameters:
serviceDescriptor- the service information to use- Returns:
- a latch ID
-
leaderLatchId
public static String leaderLatchId(String serviceName, String serviceVersion, String hostname, int port) Utility method to generate a standard latch id for a service.- Parameters:
serviceName- the name of the serviceserviceVersion- the version of the servicehostname- the host name where the service instance is runningport- the port on which the service instance is running- Returns:
- a latch ID
-
leaderLatchPath
Utility method to generate a standard latch path for a service.- Parameters:
serviceName- the name of the service- Returns:
- the latch path for the given service
-
toString
-
start
Starts the latch, possibly creating non-existent znodes in ZooKeeper first.The CuratorFramework must be started, or else a
VerifyExceptionwill be thrown.This method will ignore repeated attempts to start once the latch has been started.
- Specified by:
startin interfaceio.dropwizard.lifecycle.Managed- Throws:
com.google.common.base.VerifyException- if theCuratorFrameworkis not already startedException
-
stop
public void stop()Stops the latch. Any exceptions closing the latch are ignored, although they are logged.- Specified by:
stopin interfaceio.dropwizard.lifecycle.Managed
-
getManagedLatch
public org.apache.curator.framework.recipes.leader.LeaderLatch getManagedLatch()An "escape hatch" to get theLeaderLatchmanaged by this object.- Returns:
- the latch managed by this object
-
hasLeadershipIgnoringErrors
@CheckReturnValue public boolean hasLeadershipIgnoringErrors()Returns whether this instance is the leader, or false if there are any errors getting leadership status. This is a convenience wrapper that delegates toLeaderLatch.hasLeadership().If you want to make sure that a
falsereturn value is not due to any errors or invalid state, use eitherhasLeadership()orcheckLeadershipStatus().- Returns:
- true if the leader latch is started and this latch is the leader, otherwise false
- See Also:
-
hasLeadership()checkLeadershipStatus()LeaderLatch.hasLeadership()
-
checkLeadershipStatus
Checks whether this instance is the leader, returning aLeadershipStatusobject that callers can use to act upon.This method never throws any exception. Instead, invalid states and errors are represented in the returned
LeadershipStatus.If you only care that the latch is definitely the leader, ignoring any errors, you can use
hasLeadershipIgnoringErrors(). Or, you can usehasLeadership()if you want to check for errors and invalid state and handle those errors via an exception handler.- Returns:
- a value representing the leadership status
- See Also:
-
hasLeadership
@CheckReturnValue public boolean hasLeadership()Returns whether this instance is the leader, or throws aManagedLeaderLatchExceptionif Curator is not started yet or has been closed; this latch is not started yet or has been closed; or if there are no latch participants yet.The above-mentioned situations could happen, for example, because code at startup calls this method before Curator has been started, e.g., before the Jetty server starts in a Dropwizard application, or because the latch does not yet have participants even though Curator and the latch are both started. These restrictions should help prevent false negatives, i.e., having a
falsereturn value but the actual reason was because of some other factor.If you do not care whether there are errors or invalid state you can use
hasLeadershipIgnoringErrors(). Or, if you want to know the exact leadership status, you can usecheckLeadershipStatus().- Returns:
- true if this latch is currently the leader
- Throws:
ManagedLeaderLatchException- if this method is called and any of the restrictions mentioned above apply- See Also:
-
doesNotHaveLeadership
@CheckReturnValue public boolean doesNotHaveLeadership()This method is the negation ofhasLeadership().It may be useful in situations when an action requires leadership, and you want to exit a method early instead of wrapping the logic inside a conditional. For example:
public void runActionWhenLeader(Runnable action) { if (managedLatch.doesNotHaveLeadership()) { return; } // execute business logic, run the action, etc. }- Returns:
- true if this latch is currently NOT the leader
- Throws:
ManagedLeaderLatchException- if this method is called and any of the restrictions described inhasLeadership()apply
-
getParticipants
Get the participants (i.e., Dropwizard services) in this latch.- Returns:
- unordered collection of leader latch participants
- Throws:
ManagedLeaderLatchException- if any error occurs getting the participants
-
getLeader
public org.apache.curator.framework.recipes.leader.Participant getLeader()Get the leader of this latch.- Returns:
- the
Participantwho is the current leader - Throws:
ManagedLeaderLatchException- if any error occurs getting the leader
-
isStarted
public boolean isStarted()Check if the latch is started.- Returns:
- true if the latch state is
LeaderLatch.State.STARTED
-
isClosed
public boolean isClosed()Check if the latch is closed.- Returns:
- true if the latch state is
LeaderLatch.State.CLOSED
-
getLatchState
public org.apache.curator.framework.recipes.leader.LeaderLatch.State getLatchState()Get the current latch state.- Returns:
- the current
LeaderLatch.State
-
whenLeader
Perform the givenactionsynchronously only if this latch is currently the leader. Use this when the action does not need to return a value, and it is a "fire and forget" action.- Parameters:
action- the action to perform if this latch is the leader
-
whenLeaderAsync
Perform the givenactionasynchronously only if this latch is currently the leader. Use this when the action does not need to return a value, and it is a "fire and forget" action. However, if the returnedOptionalis present, you can use theCompletableFutureto determine when the action has completed and take some other action, etc. if you want to.- Parameters:
action- the action to perform if this latch is the leader- Returns:
- an Optional containing a CompletableFuture if this latch is the leader, otherwise an empty Optional
-
whenLeader
Perform the given action defined byresultSuppliersynchronously only if this latch is currently the leader, returning the result ofresultSupplier.- Type Parameters:
T- the result type- Parameters:
resultSupplier- the result-returning action to perform if this latch is the leader- Returns:
- an Optional containing the result if this latch is the leader, otherwise an empty Optional
-
whenLeaderAsync
Perform the given action defined byresultSupplierasynchronously only if this latch is currently the leader, returning aCompletableFuturewhose result will be the result of theresultSupplier.- Type Parameters:
T- the result type- Parameters:
resultSupplier- the result-returning action to perform if this latch is the leader- Returns:
- an Optional containing a CompletableFuture if this latch is the leader, otherwise an empty Optional
-
whenLeaderAsync
public <T> Optional<CompletableFuture<T>> whenLeaderAsync(Supplier<T> resultSupplier, Executor executor) Same aswhenLeaderAsync(Supplier)but uses suppliedexecutorinstead ofCompletableFuture's default executor.- Type Parameters:
T- the result type- Parameters:
resultSupplier- the result-returning action to perform if this latch is the leaderexecutor- the customExecutorto use- Returns:
- an Optional containing a CompletableFuture if this latch is the leader, otherwise an empty Optional
-
getId
-
getLatchPath
-