Class ManagedLeaderLatch
- java.lang.Object
-
- org.kiwiproject.curator.leader.ManagedLeaderLatch
-
- All Implemented Interfaces:
io.dropwizard.lifecycle.Managed
public class ManagedLeaderLatch extends Object implements io.dropwizard.lifecycle.Managed
Wrapper around Curator'sLeaderLatch
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
Constructors Constructor Description 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.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
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description org.apache.curator.framework.recipes.leader.LeaderLatch.State
getLatchState()
Get the current latch state.org.apache.curator.framework.recipes.leader.Participant
getLeader()
Get the leader of this latch.Collection<org.apache.curator.framework.recipes.leader.Participant>
getParticipants()
Get the participants (i.e.boolean
hasLeadership()
Returns whether this instance is the leader, or throws aManagedLeaderLatchException
if Curator is not started yet, this latch is not started yet, or there are no latch participants yet.boolean
isClosed()
Check if the latch is closed.boolean
isStarted()
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.String
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
.Optional<CompletableFuture<Void>>
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 Detail
-
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:
leaderLatchPath(String)
-
-
Method Detail
-
leaderLatchId
public static String leaderLatchId(ServiceDescriptor serviceDescriptor)
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
public static String leaderLatchPath(String serviceName)
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
-
start
public void start() throws Exception
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
-
hasLeadership
public boolean hasLeadership()
Returns whether this instance is the leader, or throws aManagedLeaderLatchException
if Curator is not started yet, this latch is not started yet, or 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.- Returns:
- true if this latch is currently the leader
- Throws:
ManagedLeaderLatchException
- if this method is called and any of the restrictions mentioned above apply
-
getParticipants
public Collection<org.apache.curator.framework.recipes.leader.Participant> 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
public void whenLeader(Runnable action)
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
public Optional<CompletableFuture<Void>> whenLeaderAsync(Runnable action)
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
public <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
.- 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
public <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
.- 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
-
-