java.lang.Object
org.elasticsearch.action.support.RefCountingListener
- All Implemented Interfaces:
Closeable
,AutoCloseable
,Releasable
A mechanism to complete a listener on the completion of some (dynamic) collection of other actions. Basic usage is as follows:
try (var refs = new RefCountingListener(finalListener)) { for (var item : collection) { runAsyncAction(item, refs.acquire()); // completes the acquired listener on completion } }The delegate listener is completed when execution leaves the try-with-resources block and every acquired reference is released. The
RefCountingListener
collects (a bounded number of) exceptions received by its subsidiary listeners, and completes the delegate
listener with an exception if (and only if) any subsidiary listener fails. However, unlike a GroupedActionListener
it leaves it
to the caller to collect the results of successful completions by accumulating them in a data structure of its choice. Also unlike a
GroupedActionListener
there is no need to declare the number of subsidiary listeners up front: listeners can be acquired
dynamically as needed. Finally, you can continue to acquire additional listeners even outside the try-with-resources block, perhaps in a
separate thread, as long as there's at least one listener outstanding:
try (var refs = new RefCountingListener(finalListener)) { for (var item : collection) { if (condition(item)) { runAsyncAction(item, refs.acquire(results::add)); } } if (flag) { runOneOffAsyncAction(refs.acquire(results::add)); return; } for (var item : otherCollection) { var itemRef = refs.acquire(); // delays completion while the background action is pending executorService.execute(() -> { try { if (condition(item)) { runOtherAsyncAction(item, refs.acquire(results::add)); } } finally { itemRef.onResponse(null); } }); } }In particular (and also unlike a
GroupedActionListener
) this works even if you don't acquire any extra refs at all: in that case,
the delegate listener is completed at the end of the try-with-resources block.-
Constructor Summary
ConstructorDescriptionRefCountingListener
(int maxExceptions, ActionListener<Void> delegate) Construct aRefCountingListener
which completesdelegate
when all refs are released.RefCountingListener
(ActionListener<Void> delegate) Construct aRefCountingListener
which completesdelegate
when all refs are released. -
Method Summary
Modifier and TypeMethodDescriptionacquire()
Acquire a reference to this object and return a listener which releases it.<Response> ActionListener<Response>
acquire
(CheckedConsumer<Response, Exception> consumer) Acquire a reference to this object and return a listener which consumes a response and releases the reference.void
close()
Release the original reference to this object, which completes the delegateActionListener
if there are no other references.boolean
toString()
-
Constructor Details
-
RefCountingListener
Construct aRefCountingListener
which completesdelegate
when all refs are released.- Parameters:
delegate
- The listener to complete when all refs are released. This listener must not throw any exception on completion. If all the acquired listeners completed successfully then so is the delegate. If any of the acquired listeners completed with failure then the delegate is completed with the first exception received, with other exceptions added to its collection of suppressed exceptions.
-
RefCountingListener
Construct aRefCountingListener
which completesdelegate
when all refs are released.- Parameters:
delegate
- The listener to complete when all refs are released. This listener must not throw any exception on completion. If all the acquired listeners completed successfully then so is the delegate. If any of the acquired listeners completed with failure then the delegate is completed with the first exception received, with other exceptions added to its collection of suppressed exceptions.maxExceptions
- The maximum number of exceptions to accumulate on failure.
-
-
Method Details
-
close
public void close()Release the original reference to this object, which completes the delegateActionListener
if there are no other references. It is invalid to call this method more than once. Doing so will trip an assertion if assertions are enabled, but will be ignored otherwise. This deviates from the contract ofCloseable
.- Specified by:
close
in interfaceAutoCloseable
- Specified by:
close
in interfaceCloseable
- Specified by:
close
in interfaceReleasable
-
acquire
Acquire a reference to this object and return a listener which releases it. The delegateActionListener
is called when all its references have been released. It is invalid to call this method once all references are released. Doing so will trip an assertion if assertions are enabled, and will throw anIllegalStateException
otherwise. It is also invalid to complete the returned listener more than once. Doing so will trip an assertion if assertions are enabled, but will be ignored otherwise. -
acquire
Acquire a reference to this object and return a listener which consumes a response and releases the reference. The delegateActionListener
is called when all its references have been released. If the consumer throws an exception, the exception is passed to the final listener as if the returned listener was completed exceptionally. It is invalid to call this method once all references are released. Doing so will trip an assertion if assertions are enabled, and will throw anIllegalStateException
otherwise. It is also invalid to complete the returned listener more than once. Doing so will trip an assertion if assertions are enabled, but will be ignored otherwise. -
toString
-
isFailing
public boolean isFailing()- Returns:
true
if at least one acquired listener has completed exceptionally, which means that the delegate listener will also complete exceptionally once all acquired listeners are completed.
-