Class CancellableSingleObjectCache<Input,Key,Value>

Type Parameters:
Input - The type of the input to the computation of the cached value.
Key - The key type. The cached value is associated with a key, and subsequent get(Input, java.util.function.BooleanSupplier, org.elasticsearch.action.ActionListener<Value>) calls compare keys of the given input value to determine whether the cached value is fresh or not. See isFresh(Key, Key).
Value - The type of the cached value.

public abstract class CancellableSingleObjectCache<Input,Key,Value> extends Object
A cache of a single object whose refresh process can be cancelled. The cached value is computed lazily on the first retrieval, and associated with a key which is used to determine its freshness for subsequent retrievals.

This is useful for things like computing stats over cluster metadata: the first time stats are requested they are computed, but subsequent calls re-use the computed value as long as they pertain to the same metadata version. If stats are requested for a different metadata version then the cached value is dropped and a new one is computed.

Retrievals happen via the async get(Input, java.util.function.BooleanSupplier, org.elasticsearch.action.ActionListener<Value>) method. If a retrieval is cancelled (e.g. the channel on which to return the stats is closed) then the computation carries on running in case another retrieval for the same key arrives in future. However if all of the retrievals for a key are cancelled and a retrieval occurs for a fresher key then the computation itself is cancelled.

Cancellation is based on polling: the refresh(Input, java.lang.Runnable, java.util.function.BooleanSupplier, org.elasticsearch.action.ActionListener<Value>) method checks whether it should abort whenever it is convenient to do so, which in turn checks all the pending retrievals to see whether they have been cancelled.

  • Constructor Details

    • CancellableSingleObjectCache

      protected CancellableSingleObjectCache(ThreadContext threadContext)
  • Method Details

    • refresh

      protected abstract void refresh(Input input, Runnable ensureNotCancelled, BooleanSupplier supersedeIfStale, ActionListener<Value> listener)
      Compute a new value for the cache.

      If an exception is thrown, or passed to the listener, then it is passed on to all waiting listeners but it is not cached so that subsequent retrievals will trigger subsequent calls to this method.

      Implementations of this method should poll for cancellation by running ensureNotCancelled whenever appropriate. The computation is cancelled if all of the corresponding retrievals have been cancelled and a retrieval has since happened for a fresher key.

      input - The input to this computation, which will be converted to a key and used to determine whether it is suitably fresh for future requests too.
      ensureNotCancelled - A Runnable which throws a TaskCancelledException if the result of the computation is no longer needed. On cancellation, notifying the listener is optional.
      supersedeIfStale - Checks whether the input to this refresh has been superseded by a fresher input. If the current input has been superseded then this supplier subscribes the listener (and corresponding cancellation checks) to the computation from the new input and returns true, indicating that no further action is needed by this invocation of refresh(). If the current input is still the freshest then it takes no action and returns false to indicate that this invocation of refresh() must proceed. Implementations of refresh() that work asynchronously, for instance by running the computation on a different thread, should use this to check for freshness when they resume.
      listener - A ActionListener which should be notified when the computation completes. If the computation fails by calling ActionListener.onFailure(java.lang.Exception) then the result is returned to the pending listeners but is not cached.
    • getKey

      protected abstract Key getKey(Input input)
      Compute the key for the given input value.
    • isFresh

      protected boolean isFresh(Key currentKey, Key newKey)
      Compute whether the currentKey is fresh enough for a retrieval associated with newKey.
      currentKey - The key of the current (cached or pending) value.
      newKey - The key associated with a new retrival.
      true if a value computed for currentKey is fresh enough to satisfy a retrieval for newKey.
    • get

      public final void get(Input input, BooleanSupplier isCancelled, ActionListener<Value> listener)
      Start a retrieval for the value associated with the given input, and pass it to the given listener.

      If a fresh-enough result is available when this method is called then the listener is notified immediately, on this thread. If a fresh-enough result is already being computed then the listener is captured and will be notified when the result becomes available, on the thread on which the refresh completes. If no fresh-enough result is either pending or available then this method starts to compute one by calling refresh(Input, java.lang.Runnable, java.util.function.BooleanSupplier, org.elasticsearch.action.ActionListener<Value>) on this thread.

      input - The input to compute the desired value, converted to a CancellableSingleObjectCache to determine if the value that's currently cached or pending is fresh enough.
      isCancelled - Returns true if the listener no longer requires the value being computed.
      listener - The listener to notify when the desired value becomes available.