Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial context API #562

Closed
wants to merge 1 commit into from
Closed

Initial context API #562

wants to merge 1 commit into from

Conversation

louiscryan
Copy link
Contributor

@jhump @ejona86 @nmittler

This is an initial skeleton for the proposed Context API, lets use this PR to iterate on what we want.

Here are some general goals....

  • Provide for cascading closure (similar to cancellation in Go's Context)
  • Simple & small enough that its OK to digest on Android
  • Provides some simple type-safety for values but strictly limits keys to strings
  • Interaction with ThreadLocal tries not to be 'magical', anything attached must be explicitly detached. GRPC guarantees that it's code will be safe in this regard.
  • Easy to adapt to your IOC container of choice

Fixes #262

* context which is already closed.
*
* @throws java.lang.IllegalStateException if this context is not current.
* @return the current context.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the current context" means "this" object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'current' means the context currently available from thread local (or root if there is nothing on the thread local)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to specify whether that is before or after the detach. If it is before, then that is 'this' object.

When would you expect to use the returned Context?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It made some of the tests more succinct. E.g.

assertSame(next, root.detach());

but I could take or leave it.

@ejona86
Copy link
Member

ejona86 commented Jun 25, 2015

@louiscryan, I think it would be useful to have some very simple examples of how an application would use the Context.

*
* @param <T>
*/
public static class Key<T> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are having get() on this class, maybe rename it to "Field", and "name" arguments to "key"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 key does seem strange here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find Field more strange than Key. I have little problem with Key, although I have said that the current get() means that if you aren't fully aware of its type you don't realize it is accessing the Context.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except that it's a Key that has a key and a value which is rather odd. If Context is essentially a map of names to values, then perhaps we should just follow the Java map naming conventions rather than inventing our own terminology. Entry?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Entry is also strange to me.

So we can treat that as one more reason to not have get(). Or maybe we should name get() something else, like lookup().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that the name of the method is the problem. The naming would even be worse for a method name lookup that returns a Key.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

??

get() returns T. lookup() would also return T. lookup() would lookup the value for the Key based on the ThreadLocal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I think I see my confusion ... Key has a defaultValue, not the value itself. I'm fine with the name Key in that case. Sorry for the noise :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to lookup() over get()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it to lookup() though it's worth pointing out that 'get' was not going to be part of the public interface.

@louiscryan
Copy link
Contributor Author

PTAL

* Provide an AutoCloseable (via Closeable) for use with try-with-resource blocks that will
* close a context and detach it.
*/
public class ContextCloseable implements Closeable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe CloseableContext?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nm ... this isn't a context.

@louiscryan
Copy link
Contributor Author

OK. I've now implemented the API and improved tests where there gaps. PTAL

* notified before listeners on the children.
*
*/
public class Context {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a discussion point: do we want this exposed at the top-level of the API in io.grpc? It doesn't seem like something that all users would necessarily use and isn't really part of the API in general. Would it make more sense in a subpackage?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think one issue is that the functionality here isn't really specific to GRPC, at some point it could easily move into it's own thing. Given that and the fact that the package would only have one or two classes in it I'm not sure it makes much of a difference either way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, fair enough. I said that realizing that there would be nothing else in a context package or module, which would seem rather odd. We can shelve this for now and defer to some later conversation on how to clearly identify what classes and interface compose our "public" API.

@Override
public ScheduledExecutorService create() {
return Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder()
.setNameFormat(name + "-%d").build());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setDaemon(true)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

/**
* Return the cause of the cancellation or {@code null} if context was cancelled without a cause.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Define behavior if context not closed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@a-veitch
Copy link

This is very different conceptually from the current way context-ish things are done in the C++/C side of gRPC. On that side, I see different context classes for client and server, and several first class components (deadline, auth context, and census context (which will include tracing context, tags etc.); the latter two are at least partially opaque), plus arbitrary key/value metadata pairs. Contexts are not immutable. Is there a desire to have the API's be similar in API/usage, or is this a non-goal?

@louiscryan
Copy link
Contributor Author

I think the design tradeoffs for Java are different than those for C/C++
and what would be idiomatic in one would not necessarily be idiomatic for
the other. The goal is of course to provide the same concepts and the same
functionality across languages but to allow them to vary in idiom.

  • For Java we haven't seen a need to have a different class between client
    and server, this seems like a simplification.
  • We have first-class support for deadline (see the withDeadline,
    withCancellation methods)
  • We are able to achieve strongly-typed bindings for auth/tracing etc
    without requiring explicit support for them in the Context class itself
    (see the Key class)
  • We support mutabilty but the mechanism is different than in C++. This was
    done for performance and footprint reasons and is based on the assumption
    that reads are more common than mutations. We do not put an immutability
    restriction on data stored in the context and folks are free to optimize
    these for their use-cases as they see fit.

On Wed, Jul 15, 2015 at 1:22 PM, Alistair Veitch [email protected]
wrote:

This is very different conceptually from the current way context-ish
things are done in the C++/C side of gRPC. On that side, I see different
context classes for client and server, and several first class components
(deadline, auth context, and census context (which will include tracing
context, tags etc.); the latter two are at least partially opaque), plus
arbitrary key/value metadata pairs. Contexts are not immutable. Is there a
desire to have the API's be similar in API/usage, or is this a non-goal?


Reply to this email directly or view it on GitHub
#562 (comment).

@louiscryan
Copy link
Contributor Author

Given that we need to make some forward progress on context binding within GRPC itself I'll be checking this in soon. The GRPC APIs are not frozen yet so there's plenty of scope for change and feedback so I encourage folks to get their hands dirty with it.

@codefromthecrypt
Copy link
Contributor

codefromthecrypt commented Jul 16, 2015 via email

…mount of state through the

call stack and across thread boundaries.

Strongly modeled after the Go context API https://blog.golang.org/context with support for
- cancellation propagation & cancellation listeners
- typed value binding
- timeout/deadline

The major difference with Go is that ThreadLocal is used for propagation instead of parameter
passing as this is considered more idiomatic for Java.
@louiscryan
Copy link
Contributor Author

Merged as f612116

@louiscryan louiscryan closed this Jul 21, 2015
@lock lock bot locked as resolved and limited conversation to collaborators Jan 22, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants