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 aManagedLeaderLatchException
since that method can potentially throw one. See its documentation for the possible situations in which an exception could be thrown.
-
Constructor Summary
ConstructorDescriptionManagedLeaderLatch
(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 aLeadershipStatus
object that callers can use to act upon.boolean
This method is the negation ofhasLeadership()
.getId()
org.apache.curator.framework.recipes.leader.LeaderLatch.State
Get the current latch state.org.apache.curator.framework.recipes.leader.Participant
Get the leader of this latch.org.apache.curator.framework.recipes.leader.LeaderLatch
An "escape hatch" to get theLeaderLatch
managed by this object.Collection<org.apache.curator.framework.recipes.leader.Participant>
Get the participants (i.e., Dropwizard services) in this latch.boolean
Returns whether this instance is the leader, or throws aManagedLeaderLatchException
if 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.boolean
Returns whether this instance is the leader, or false if there are any errors getting leadership status.boolean
isClosed()
Check if the latch is closed.boolean
Check if the latch is started.static String
leaderLatchId
(String serviceName, String serviceVersion, String hostname, int port) Utility method to generate a standard latch id for a service.static String
leaderLatchId
(ServiceDescriptor serviceDescriptor) Utility method to generate a standard latch id for a service.static String
leaderLatchPath
(String serviceName) Utility method to generate a standard latch path for a service.void
start()
Starts the latch, possibly creating non-existent znodes in ZooKeeper first.void
stop()
Stops the latch.toString()
void
whenLeader
(Runnable action) Perform the givenaction
synchronously only if this latch is currently the leader.<T> Optional<T>
whenLeader
(Supplier<T> resultSupplier) Perform the given action defined byresultSupplier
synchronously only if this latch is currently the leader, returning the result ofresultSupplier
.whenLeaderAsync
(Runnable action) Perform the givenaction
asynchronously only if this latch is currently the leader.<T> Optional<CompletableFuture<T>>
whenLeaderAsync
(Supplier<T> resultSupplier) Perform the given action defined byresultSupplier
asynchronously only if this latch is currently the leader, returning aCompletableFuture
whose result will be the result of theresultSupplier
.<T> Optional<CompletableFuture<T>>
whenLeaderAsync
(Supplier<T> resultSupplier, Executor executor) Same aswhenLeaderAsync(Supplier)
but uses suppliedexecutor
instead 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
- theCuratorFramework
client that this latch should useserviceDescriptor
- service metadatalisteners
- zero or moreLeaderLatchListener
instances 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
serviceName
should be the generic name of a service, e.g. "payment-service" or "order-service", instead of a unique service identifier.- Parameters:
client
- theCuratorFramework
client 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 moreLeaderLatchListener
instances 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
VerifyException
will be thrown.This method will ignore repeated attempts to start once the latch has been started.
- Specified by:
start
in interfaceio.dropwizard.lifecycle.Managed
- Throws:
com.google.common.base.VerifyException
- if theCuratorFramework
is not already startedException
-
stop
public void stop()Stops the latch. Any exceptions closing the latch are ignored, although they are logged.- Specified by:
stop
in interfaceio.dropwizard.lifecycle.Managed
-
getManagedLatch
public org.apache.curator.framework.recipes.leader.LeaderLatch getManagedLatch()An "escape hatch" to get theLeaderLatch
managed 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
false
return 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 aLeadershipStatus
object 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 aManagedLeaderLatchException
if 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
false
return 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
Participant
who 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 givenaction
synchronously 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 givenaction
asynchronously 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 returnedOptional
is present, you can use theCompletableFuture
to 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 byresultSupplier
synchronously 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 byresultSupplier
asynchronously only if this latch is currently the leader, returning aCompletableFuture
whose 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 suppliedexecutor
instead 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 customExecutor
to use- Returns:
- an Optional containing a CompletableFuture if this latch is the leader, otherwise an empty Optional
-
getId
-
getLatchPath
-