-
Notifications
You must be signed in to change notification settings - Fork 290
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
RFC: fx.Context as a struct #126
Comments
There may be performance implications to using a struct, since we'll be passing the struct by value, and when a by-value object is converted to an interface, it requires an allocation. Since the We should ensure there's no performance hit if we want to do this. |
cc @anuptalwalkar who is doing the implementation |
And yes, the interface conversion was the primary motivation for us using an interface in he first place. |
If this affects perf negatively, an interface can still be used to get package fx
type Context interface {
context.Context
// unexported function to ensure only this package implements this
// interface.
fx()
// ...
}
func Upgrade(context.Context) Context { // Better name TBD
return &context{...}
}
func NewContext(context.Context, Host) Context {
// ...
}
type context struct {
// ..
}
func (c *context) fx() {}
func (c *context) Logger() Logger {
return GetLogger(c.Context)
} This gets rid of the |
FWIW I was imagining Logger() and friends would be impure (e.g. have side
effects of caching the return value)
…On Wed, Dec 14, 2016 at 11:26 AM Abhinav Gupta ***@***.***> wrote:
If this affects perf negatively, an interface can still be used to get
context.Context compatibility provided that UberFx maintains control of
all
implementations by adding a private method to the interface and providing a
public function to upgrade a context.Context back to an fx.Context.
package fx
type Context interface {
context.Context
// unexported function to ensure only this package implements this
// interface.
fx()
// ...
}
func Upgrade(context.Context) Context { // Better name TBD
return &context{...}
}
func NewContext(context.Context, Host) Context {
// ...
}
type context struct {
// ..
}
func (c *context) fx() {}
func (c *context) Logger() Logger {
return GetLogger(c.Context)
}
This gets rid of the fx.Context -> context.Context alloc.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#126 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAF7P4KCgTYQ9TQNuUlfXV5IQEWQGQNJks5rIELTgaJpZM4LNTGE>
.
|
Private method on the interface is a good idea. I'd avoid adding the |
I like the private method idea to keep the implementation restricted. |
@anuptalwalkar fxctx := fx.NewContext(...)
ctx := context.WithValue(fxctx, ...)
fxctx2 := ctx.(fx.Context) // this will panic The two solutions recommended here would solve that. @prashantv The upgrade function is needed to solve the problem mentioned Imagine that an UberFx InboundMiddleware adds UberFx information to incoming func (m *ctxMiddleware) Handle(
ctx context.Context, ..., h transport.UnaryHandler,
) error {
fxctx := fx.NewContext(ctx, m.Host)
return h.Handle(fxctx, ...)
} We get this context as a func WrapUnary(h fxthrift.UnaryHandlerFunc) yarpcthrift.UnaryHandler {
return func(ctx context.Context, ...) error {
fxctx := upgrade(ctx)
return h(fxctx, ...)
}
} |
I am following the same approach in the refactoring. Well, |
|
Let's go with Abhinavs suggestion of pure functions and structs and write
some benchmarks. It seems cleanest.
…On Wed, Dec 14, 2016 at 2:36 PM Abhinav Gupta ***@***.***> wrote:
ctx.(fx.Context) won't work if anything between the UberFx middleware and
WrapUnary calls context.WithValue on the context because the returned ctx
will not have the added fx.Context functions anymore.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#126 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAF7P7z_dipuKfWLDmbZRRIafUkjKdGvks5rIG9ugaJpZM4LNTGE>
.
|
Added benchmarks for Context conversion - #131 |
Following up our discussion yesterday: I would like to propose the following:
fx.Context
is a struct that embedscontext.Context
rather than aninterface.
fx.Context
actually just usecontext.WithValue
rather than wrapping acontext.Context
in a newtype. Value accessors will be defined for all UberFx values.
fx.Context
which just call theaccessor on itself.
Specifically,
This has a few advantages:
Discoverability by having methods on
fx.Context
.Full compatibility with
context.Context
andWithValue
. You won't loseUberFx information if you do,
Downgrading to
context.Context
and upgrading back tofx.Context
justworks.
The only thing to keep in mind is that accessors have to have reasonable
behavior for the case where a
context.Context
does not have UberFxinformation on it.
Thoughts?
CC @breerly @kriskowal @willhug @sectioneight
The text was updated successfully, but these errors were encountered: