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'sLeaderLatchwhich 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
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.StategetLatchState()Get the current latch state.org.apache.curator.framework.recipes.leader.ParticipantgetLeader()Get the leader of this latch.Collection<org.apache.curator.framework.recipes.leader.Participant>getParticipants()Get the participants (i.e.booleanhasLeadership()Returns whether this instance is the leader, or throws aManagedLeaderLatchExceptionif Curator is not started yet, this latch is not started yet, or there are no latch participants yet.booleanisClosed()Check if the latch is closed.booleanisStarted()Check 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.StringtoString()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.Optional<CompletableFuture<Void>>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 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- 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:
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 ExceptionStarts 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
-
hasLeadership
public boolean hasLeadership()
Returns whether this instance is the leader, or throws aManagedLeaderLatchExceptionif 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
falsereturn 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
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
public void whenLeader(Runnable action)
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
public Optional<CompletableFuture<Void>> whenLeaderAsync(Runnable action)
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
public <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.- 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 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
-
-