Class Context
- Direct Known Subclasses:
Context.CancellableContext
- Security principals and credentials.
- Local and distributed tracing information.
A Context object can be attached
to the Context.Storage
, which effectively
forms a scope for the context. The scope is bound to the current thread. Within a scope,
its Context is accessible even across API boundaries, through current()
. The scope is
later exited by detaching
the Context.
Context objects are immutable and inherit state from their parent. To add or overwrite the current state a new context object must be created and then attached, replacing the previously bound context. For example:
Context withCredential = Context.current().withValue(CRED_KEY, cred); withCredential.run(new Runnable() { public void run() { readUserRecords(userId, CRED_KEY.get()); } });
Contexts are also used to represent a scoped unit of work. When the unit of work is done the
context must be cancelled. This cancellation will cascade to all descendant contexts. You can
add a Context.CancellationListener
to a context to be notified when it or one of its ancestors
has been cancelled. Cancellation does not release the state stored by a context and it's
perfectly valid to attach()
an already cancelled context to make it current. To cancel a
context (and its descendants) you first create a Context.CancellableContext
and when you need to
signal cancellation call Context.CancellableContext.cancel(java.lang.Throwable)
or Context.CancellableContext.detachAndCancel(io.grpc.Context, java.lang.Throwable)
.
Contexts can also be created with a timeout relative to the system nano clock which will cause it to automatically cancel at the desired time.
Notes and cautions on use:
- Every
attach()
should have adetach()
in the same method. And every CancellableContext should be cancelled at some point. Breaking these rules may lead to memory leaks. - While Context objects are immutable they do not place such a restriction on the state they store.
- Context is not intended for passing optional parameters to an API and developers should take care to avoid excessive dependence on context when designing an API.
- Do not mock this class. Use
ROOT
for a non-null instance.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final class
A context which inherits cancellation from its parent but which can also be independently cancelled and which will propagate cancellation to its descendants.static interface
A listener notified on context cancellation.(package private) static @interface
(package private) static @interface
private static enum
private static final class
Stores listener and executor pair.static final class
Key for indexing values stored in a context.private static final class
static class
Defines the mechanisms for attaching and detaching the "current" context. -
Field Summary
FieldsModifier and TypeFieldDescription(package private) final Context.CancellableContext
(package private) static final int
(package private) final int
(package private) final PersistentHashArrayMappedTrie.Node
<Context.Key<?>, Object> (package private) static final Logger
static final Context
The logical root context which is the ultimate ancestor of all contexts. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprivate
Context()
Construct forROOT
.private
Context
(Context parent, PersistentHashArrayMappedTrie.Node<Context.Key<?>, Object> keyValueEntries) Construct a context that cannot be cancelled but will cascade cancellation from its parent if it is cancellable.private
Context
(PersistentHashArrayMappedTrie.Node<Context.Key<?>, Object> keyValueEntries, int generation) Construct a context that cannot be cancelled and will not cascade cancellation from its parent. -
Method Summary
Modifier and TypeMethodDescriptionvoid
addListener
(Context.CancellationListener cancellationListener, Executor executor) Add a listener that will be notified when the context becomes cancelled.attach()
Attach this context, thus enter a new scope within which this context iscurrent()
.<V> V
(package private) static Context.CancellableContext
cancellableAncestor
(Context parent) Returnsparent
if it is aContext.CancellableContext
, otherwise returns the parent'scancellableAncestor
.If a contextisCancelled()
then return the cause of the cancellation ornull
if context was cancelled without a cause.(package private) static <T> T
checkNotNull
(T reference, Object errorMessage) static Context
current()
Return the context associated with the current scope, will never returnnull
.static Executor
Create an executor that propagates thecurrent()
context whenExecutor.execute(java.lang.Runnable)
is called as thecurrent()
context of theRunnable
scheduled.void
Reverse anattach()
, restoring the previous context and exiting the current scope.fork()
Create a new context which propagates the values of this context but does not cascade its cancellation.A context may have an associatedDeadline
at which it will be automatically cancelled.boolean
Is this context cancelled.(package private) boolean
static <T> Context.Key
<T> Create aContext.Key
with the given debug name.static <T> Context.Key
<T> keyWithDefault
(String debugString, T defaultValue) Create aContext.Key
with the given debug name and default value.(package private) int
void
removeListener
(Context.CancellationListener cancellationListener) Remove aContext.CancellationListener
.void
(package private) static Context.Storage
storage()
private static void
validateGeneration
(int generation) If the ancestry chain length is unreasonably long, then print an error to the log and record the stack trace.Create a new context which is independently cancellable and also cascades cancellation from its parent.withDeadline
(Deadline newDeadline, ScheduledExecutorService scheduler) Create a new context which will cancel itself at the givenDeadline
.withDeadlineAfter
(long duration, TimeUnit unit, ScheduledExecutorService scheduler) Create a new context which will cancel itself after the givenduration
from now.<V> Context
withValue
(Context.Key<V> k1, V v1) Create a new context with the given key value set.<V1,
V2> Context withValues
(Context.Key<V1> k1, V1 v1, Context.Key<V2> k2, V2 v2) Create a new context with the given key value set.<V1,
V2, V3>
ContextwithValues
(Context.Key<V1> k1, V1 v1, Context.Key<V2> k2, V2 v2, Context.Key<V3> k3, V3 v3) Create a new context with the given key value set.<V1,
V2, V3, V4>
ContextwithValues
(Context.Key<V1> k1, V1 v1, Context.Key<V2> k2, V2 v2, Context.Key<V3> k3, V3 v3, Context.Key<V4> k4, V4 v4) Create a new context with the given key value set.<C> Callable
<C>
-
Field Details
-
log
-
CONTEXT_DEPTH_WARN_THRESH
static final int CONTEXT_DEPTH_WARN_THRESH- See Also:
-
ROOT
The logical root context which is the ultimate ancestor of all contexts. This context is not cancellable and so will not cascade cancellation or retain listeners.Never assume this is the default context for new threads, because
Context.Storage
may define a default context that is different from ROOT. -
cancellableAncestor
-
keyValueEntries
-
generation
final int generation
-
-
Constructor Details
-
Context
private Context(PersistentHashArrayMappedTrie.Node<Context.Key<?>, Object> keyValueEntries, int generation) Construct a context that cannot be cancelled and will not cascade cancellation from its parent. -
Context
private Context(Context parent, PersistentHashArrayMappedTrie.Node<Context.Key<?>, Object> keyValueEntries) Construct a context that cannot be cancelled but will cascade cancellation from its parent if it is cancellable. -
Context
private Context()Construct forROOT
.
-
-
Method Details
-
storage
-
key
Create aContext.Key
with the given debug name.- Parameters:
debugString
- a name intended for debugging purposes and does not impact behavior. Multiple different keys may have the same debugString. The value should be not null.
-
keyWithDefault
Create aContext.Key
with the given debug name and default value.- Parameters:
debugString
- a name intended for debugging purposes and does not impact behavior. Multiple different keys may have the same debugString. The value should be not null.
-
current
Return the context associated with the current scope, will never returnnull
.Will never return
Context.CancellableContext
even if one is attached, instead aContext
is returned with the same properties and lifetime. This is to avoid code stealing the ability to cancel arbitrarily. -
withCancellation
Create a new context which is independently cancellable and also cascades cancellation from its parent. Callers must ensure that eitherContext.CancellableContext.cancel(Throwable)
orContext.CancellableContext.detachAndCancel(Context, Throwable)
are called at a later point, in order to allow this context to be garbage collected.Sample usage:
Context.CancellableContext withCancellation = Context.current().withCancellation(); try { withCancellation.run(new Runnable() { public void run() { Context current = Context.current(); while (!current.isCancelled()) { keepWorking(); } } }); } finally { withCancellation.cancel(null); }
-
withDeadlineAfter
public Context.CancellableContext withDeadlineAfter(long duration, TimeUnit unit, ScheduledExecutorService scheduler) Create a new context which will cancel itself after the givenduration
from now. The returned context will cascade cancellation of its parent. Callers may explicitly cancel the returned context prior to the deadline just as forwithCancellation()
. If the unit of work completes before the deadline, the context should be explicitly cancelled to allow it to be garbage collected.Sample usage:
Context.CancellableContext withDeadline = Context.current() .withDeadlineAfter(5, TimeUnit.SECONDS, scheduler); try { withDeadline.run(new Runnable() { public void run() { Context current = Context.current(); while (!current.isCancelled()) { keepWorking(); } } }); } finally { withDeadline.cancel(null); }
-
withDeadline
public Context.CancellableContext withDeadline(Deadline newDeadline, ScheduledExecutorService scheduler) Create a new context which will cancel itself at the givenDeadline
. The returned context will cascade cancellation of its parent. Callers may explicitly cancel the returned context prior to the deadline just as forwithCancellation()
. If the unit of work completes before the deadline, the context should be explicitly cancelled to allow it to be garbage collected.Sample usage:
Context.CancellableContext withDeadline = Context.current() .withDeadline(someReceivedDeadline, scheduler); try { withDeadline.run(new Runnable() { public void run() { Context current = Context.current(); while (!current.isCancelled() && moreWorkToDo()) { keepWorking(); } } }); } finally { withDeadline.cancel(null); }
-
withValue
Create a new context with the given key value set. The new context will cascade cancellation from its parent.Context withCredential = Context.current().withValue(CRED_KEY, cred); withCredential.run(new Runnable() { public void run() { readUserRecords(userId, CRED_KEY.get()); } });
Note that multiple calls to
withValue(io.grpc.Context.Key<V>, V)
can be chained together. That is,context.withValues(K1, V1, K2, V2); // is the same as context.withValue(K1, V1).withValue(K2, V2);
Nonetheless,
Context
should not be treated like a general purpose map with a large number of keys and values — combine multiple related items together into a single key instead of separating them. But if the items are unrelated, have separate keys for them. -
withValues
Create a new context with the given key value set. The new context will cascade cancellation from its parent. -
withValues
public <V1,V2, Context withValuesV3> (Context.Key<V1> k1, V1 v1, Context.Key<V2> k2, V2 v2, Context.Key<V3> k3, V3 v3) Create a new context with the given key value set. The new context will cascade cancellation from its parent. -
withValues
public <V1,V2, Context withValuesV3, V4> (Context.Key<V1> k1, V1 v1, Context.Key<V2> k2, V2 v2, Context.Key<V3> k3, V3 v3, Context.Key<V4> k4, V4 v4) Create a new context with the given key value set. The new context will cascade cancellation from its parent.For more than 4 key-value pairs, note that multiple calls to
withValue(io.grpc.Context.Key<V>, V)
can be chained together. That is,context.withValues(K1, V1, K2, V2); // is the same as context.withValue(K1, V1).withValue(K2, V2);
Nonetheless,
Context
should not be treated like a general purpose map with a large number of keys and values — combine multiple related items together into a single key instead of separating them. But if the items are unrelated, have separate keys for them. -
fork
Create a new context which propagates the values of this context but does not cascade its cancellation. -
attach
Attach this context, thus enter a new scope within which this context iscurrent()
. The previously current context is returned. It is allowed to attach contexts whereisCancelled()
istrue
.Instead of using
attach()
anddetach(Context)
most use-cases are better served by using therun(Runnable)
orcall(java.util.concurrent.Callable)
to execute work immediately within a context's scope. If work needs to be done in other threads it is recommended to use the 'wrap' methods or to use a propagating executor.All calls to
attach()
should have a correspondingdetach(Context)
within the same method:Context previous = someContext.attach(); try { // Do work } finally { someContext.detach(previous); }
-
detach
Reverse anattach()
, restoring the previous context and exiting the current scope.This context should be the same context that was previously
attached
. The provided replacement should be what was returned by the sameattach()
call. If anattach()
and adetach()
meet above requirements, they match.It is expected that between any pair of matching
attach()
anddetach()
, allattach()
es anddetach()
es are called in matching pairs. If this method finds that this context is notcurrent
, either you or some code in-between are not detaching correctly, and a SEVERE message will be logged but the context to attach will still be bound. Never useContext.current().detach()
, as this will compromise this error-detecting mechanism. -
isCurrent
boolean isCurrent() -
isCancelled
public boolean isCancelled()Is this context cancelled. -
cancellationCause
If a contextisCancelled()
then return the cause of the cancellation ornull
if context was cancelled without a cause. If the context is not yet cancelled will always returnnull
.The cancellation cause is provided for informational purposes only and implementations should generally assume that it has already been handled and logged properly.
-
getDeadline
A context may have an associatedDeadline
at which it will be automatically cancelled.- Returns:
- A
Deadline
ornull
if no deadline is set.
-
addListener
Add a listener that will be notified when the context becomes cancelled. -
removeListener
Remove aContext.CancellationListener
. -
listenerCount
int listenerCount() -
run
- Parameters:
r
-Runnable
to run.
-
call
-
wrap
-
wrap
-
fixedContextExecutor
Wrap anExecutor
so that it always executes with this context as thecurrent()
context. It is generally expected thatcurrentContextExecutor(Executor)
would be used more commonly than this method.One scenario in which this executor may be useful is when a single thread is sharding work to multiple threads.
- See Also:
-
currentContextExecutor
Create an executor that propagates thecurrent()
context whenExecutor.execute(java.lang.Runnable)
is called as thecurrent()
context of theRunnable
scheduled. Note that this is a static method.- See Also:
-
checkNotNull
-
cancellableAncestor
Returnsparent
if it is aContext.CancellableContext
, otherwise returns the parent'scancellableAncestor
. -
validateGeneration
private static void validateGeneration(int generation) If the ancestry chain length is unreasonably long, then print an error to the log and record the stack trace.
-