Package com.yahoo.vespa.curator.api
Interface VespaCurator.SingletonWorker
- Enclosing interface:
- VespaCurator
public static interface VespaCurator.SingletonWorker
Callback interface for processes of which only a single instance should be active at any time, across all
containers in the cluster, and across all component generations.
Notes to implementors:
activate()
is called by the system on a singleton whenever it is the newest registered singleton in this container, and this container has the lease for the ID with which the singleton was registered. Seeid()
,VespaCurator.register(com.yahoo.vespa.curator.api.VespaCurator.SingletonWorker, java.time.Duration)
andVespaCurator.isActive(java.lang.String)
.deactivate()
is called by the system on a singleton which is currently active whenever the above no longer holds. SeeVespaCurator.unregister(com.yahoo.vespa.curator.api.VespaCurator.SingletonWorker, java.time.Duration)
.- Callbacks for the same ID are always invoked by the same thread, in serial; the callbacks must return in a timely manner, but are encouraged to throw exceptions when something's wrong.
- Activation and deactivation may be triggered by:
- the container acquiring or losing the activation lease; or
- registration of unregistration of a new or obsolete singleton.
- A container without any registered singletons will not attempt to hold the activation lease.
Sample usage:
public class SingletonHolder extends AbstractComponent { private static final Duration timeout = Duration.ofSeconds(10); private final VespaCurator curator; private final SingletonWorker singleton; public SingletonHolder(VespaCurator curator) { this.curator = curator; this.singleton = new Singleton(); curator.register(singleton, timeout); } @Override public void deconstruct() { curator.unregister(singleton, timeout); singleton.shutdown(); } } public class Singleton implements SingletonWorker { private final SharedResource resource = ...; // Shared resource that requires exclusive access. private final ExecutorService executor = Executors.newSingleThreadExecutor(); private final AtomicBoolean running = new AtomicBoolean(); private Future<?> future = null; @Override public void activate() { try { resource.open(5, TimeUnit.SECONDS); } // Verify resource works here, and propagate any errors out. catch (Exception e) { resource.close(); throw new RuntimeException("failed opening " + resource, e); } running.set(true); future = executor.submit(this::doWork); } @Override public void deactivate() { running.set(false); try { future.get(5, TimeUnit.SECONDS); } catch (Exception e) { ... } finally { resource.close(); } } private void doWork() { while (running.get()) { ... } // Regularly check whether we should keep running. } public void shutdown() { executor.shutdownNow(); // Executor should have no running tasks at this point. } }
-
Method Summary
Modifier and TypeMethodDescriptionvoid
activate()
Called by the system whenever this singleton becomes the single active worker.void
Called by the system whenever this singleton is no longer the single active worker.default String
id()
The singleton ID to use when registering this with aVespaCurator
.
-
Method Details
-
activate
void activate()Called by the system whenever this singleton becomes the single active worker. If this is triggered because the container obtains the activation lease, and activation fails, then the container immediately releases the lease, so another container may acquire it instead. -
deactivate
void deactivate()Called by the system whenever this singleton is no longer the single active worker. -
id
The singleton ID to use when registering this with aVespaCurator
. At most one singleton worker with the given ID will be active, in the cluster, at any time.VespaCurator.isActive(String)
may be polled to see whether this container is currently allowed to have an active singleton with the given ID.
-