Package io.grpc

Class Context

  • Direct Known Subclasses:
    Context.CancellableContext

    public class Context
    extends java.lang.Object
    A context propagation mechanism which can carry scoped-values across API boundaries and between threads. Examples of state propagated via context include:
    • 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 a detach() 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 Classes 
      Modifier and Type Class Description
      static class  Context.CancellableContext
      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  Context.CancellationListener
      A listener notified on context cancellation.
      static class  Context.Key<T>
      Key for indexing values stored in a context.
      static class  Context.Storage
      Defines the mechanisms for attaching and detaching the "current" context.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      static Context ROOT
      The logical root context which is the ultimate ancestor of all contexts.
    • Field Detail

      • ROOT

        public static final Context 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.

    • Method Detail

      • key

        public static <T> Context.Key<T> key​(java.lang.String debugString)
        Create a Context.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

        public static <T> Context.Key<T> keyWithDefault​(java.lang.String debugString,
                                                        T defaultValue)
        Create a Context.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

        public static Context current()
        Return the context associated with the current scope, will never return null.

        Will never return Context.CancellableContext even if one is attached, instead a Context is returned with the same properties and lifetime. This is to avoid code stealing the ability to cancel arbitrarily.

      • withCancellation

        public Context.CancellableContext withCancellation()
        Create a new context which is independently cancellable and also cascades cancellation from its parent. Callers must ensure that either Context.CancellableContext.cancel(Throwable) or Context.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,
                                                            java.util.concurrent.TimeUnit unit,
                                                            java.util.concurrent.ScheduledExecutorService scheduler)
        Create a new context which will cancel itself after the given duration from now. The returned context will cascade cancellation of its parent. Callers may explicitly cancel the returned context prior to the deadline just as for withCancellation(). 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,
                                                       java.util.concurrent.ScheduledExecutorService scheduler)
        Create a new context which will cancel itself at the given Deadline. The returned context will cascade cancellation of its parent. Callers may explicitly cancel the returned context prior to the deadline just as for withCancellation(). 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

        public <V> Context withValue​(Context.Key<V> k1,
                                     V v1)
        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

        public <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. The new context will cascade cancellation from its parent.
      • withValues

        public <V1,​V2,​V3> Context withValues​(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,​V3,​V4> Context withValues​(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

        public Context fork()
        Create a new context which propagates the values of this context but does not cascade its cancellation.
      • attach

        public Context attach()
        Attach this context, thus enter a new scope within which this context is current(). The previously current context is returned. It is allowed to attach contexts where isCancelled() is true.

        Instead of using attach() and detach(Context) most use-cases are better served by using the run(Runnable) or call(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 corresponding detach(Context) within the same method:

        Context previous = someContext.attach();
         try {
           // Do work
         } finally {
           someContext.detach(previous);
         }
      • detach

        public void detach​(Context toAttach)
        Reverse an attach(), 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 same attach() call. If an attach() and a detach() meet above requirements, they match.

        It is expected that between any pair of matching attach() and detach(), all attach()es and detach()es are called in matching pairs. If this method finds that this context is not current, 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 use Context.current().detach(), as this will compromise this error-detecting mechanism.

      • isCancelled

        public boolean isCancelled()
        Is this context cancelled.
      • cancellationCause

        public java.lang.Throwable cancellationCause()
        If a context isCancelled() then return the cause of the cancellation or null if context was cancelled without a cause. If the context is not yet cancelled will always return null.

        The cancellation cause is provided for informational purposes only and implementations should generally assume that it has already been handled and logged properly.

      • getDeadline

        public Deadline getDeadline()
        A context may have an associated Deadline at which it will be automatically cancelled.
        Returns:
        A Deadline or null if no deadline is set.
      • addListener

        public void addListener​(Context.CancellationListener cancellationListener,
                                java.util.concurrent.Executor executor)
        Add a listener that will be notified when the context becomes cancelled.
      • run

        public void run​(java.lang.Runnable r)
        Immediately run a Runnable with this context as the current() context.
        Parameters:
        r - Runnable to run.
      • call

        public <V> V call​(java.util.concurrent.Callable<V> c)
                   throws java.lang.Exception
        Immediately call a Callable with this context as the current() context.
        Parameters:
        c - Callable to call.
        Returns:
        result of call.
        Throws:
        java.lang.Exception
      • wrap

        public java.lang.Runnable wrap​(java.lang.Runnable r)
        Wrap a Runnable so that it executes with this context as the current() context.
      • wrap

        public <C> java.util.concurrent.Callable<C> wrap​(java.util.concurrent.Callable<C> c)
        Wrap a Callable so that it executes with this context as the current() context.
      • fixedContextExecutor

        public java.util.concurrent.Executor fixedContextExecutor​(java.util.concurrent.Executor e)
        Wrap an Executor so that it always executes with this context as the current() context. It is generally expected that currentContextExecutor(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(Executor)
      • currentContextExecutor

        public static java.util.concurrent.Executor currentContextExecutor​(java.util.concurrent.Executor e)
        Create an executor that propagates the current() context when Executor.execute(java.lang.Runnable) is called as the current() context of the Runnable scheduled. Note that this is a static method.
        See Also:
        fixedContextExecutor(Executor)