An example of passing it around would be:

func (f *MyFunc) Invoke(ctx statefun.Context, message statefun.Message)
error {

    logger := NewLogger()
    ctx.SetContext(ctxzap.ToContext(ctx, logger))

    return SomeOtherFunc(ctx)
}

func SomeOtherFunc(ctx context.Context) error {

    logger := ctxzap.Extract(ctx)
    logger.Info(...)

    return nil
}

This would also work with further nested calls, so long as the context is
passed to them.

On Fri, Feb 18, 2022 at 11:23 AM Galen Warren <ga...@cvillewarrens.com>
wrote:

> Ha, our emails keep passing.
>
> I've been playing around with options locally, and the SetContext option
> seems to be the most flexible (and non-breaking), imo.
>
> The implementation would be trivial, just add:
>
> SetContext(ctx context.Context)
>
> ... to the statefun.Context interface, which is implemented as:
>
> func (s *statefunContext) SetContext(ctx context.Context) {
> s.Context = ctx
> }
>
>
>
>
> On Fri, Feb 18, 2022 at 11:18 AM Austin Cawley-Edwards <
> austin.caw...@gmail.com> wrote:
>
>> It would be helpful to have a small example though, if you have on Galen,
>> to see how you're passing it around.
>>
>> On Fri, Feb 18, 2022 at 11:10 AM Austin Cawley-Edwards <
>> austin.caw...@gmail.com> wrote:
>>
>> > Looking through the statefun Context interface, it indeed doesn't give
>> > access to the underlying context.Context and the only implementation is
>> > package-private [1]. I don't think there would be a way to update the
>> > statfun.Context interface without introducing breaking changes, but if
>> we
>> > were to make that implementation public, that might be a stopgap
>> solution.
>> > e.g.,
>> >
>> > ```
>> > type StatefunContext struct {
>> > // expose embedded context
>> > context.Context
>> >
>> > // make the mutext private
>> > mu sync.Mutex
>> >
>> > // keep internals private
>> > self     Address
>> > caller   *Address
>> > storage  *storage
>> > response *protocol.FromFunction_InvocationResponse
>> > }
>> > ```
>> >
>> > You could then do a type assertion in the handlers for this type of
>> > context, and modify the context on it directly. It would be a bit ugly,
>> but
>> > may work.
>> >
>> > ```
>> > func (s aFunc) Invoke(ctx Context, message Message) error {
>> >   if sCtx, ok := ctx.(*statefun.StatefunContext); ok {
>> >     sCtx.Context = context.WithValue(sCtx.Context, "logger", aLogger)
>> >   }
>> >   // ...
>> > }
>> > ```
>> >
>> > Let me know what you all think,
>> > Austin
>> >
>> >
>> > [1]:
>> >
>> https://github.com/apache/flink-statefun/blob/1dfe226d85fea05a46c8ffa688175b4c0f2d4900/statefun-sdk-go/v3/pkg/statefun/context.go#L66-L73
>> >
>> >
>> > On Fri, Feb 18, 2022 at 11:03 AM Galen Warren <ga...@cvillewarrens.com>
>> > wrote:
>> >
>> >> Sorry Austin, I didn't see your response before I replied. Yes, we're
>> >> saying the same thing.
>> >>
>> >> On Fri, Feb 18, 2022 at 10:56 AM Austin Cawley-Edwards <
>> >> austin.caw...@gmail.com> wrote:
>> >>
>> >> > Hey all, jumping in. This makes sense to me – for instance to attach
>> a
>> >> > logger with some common metadata, e.g trace ID for the request? This
>> is
>> >> > common in go to add arbitrary items without updating the method
>> >> signatures,
>> >> > similar to thread local storage in Java.
>> >> >
>> >> > On Fri, Feb 18, 2022 at 10:53 AM Till Rohrmann <trohrm...@apache.org
>> >
>> >> > wrote:
>> >> >
>> >> > > Thanks for the clarification Galen. If you call the other Go
>> >> functions,
>> >> > > then you could also pass the other values as separate arguments to
>> >> these
>> >> > > functions, can't you?
>> >> > >
>> >> > > Cheers,
>> >> > > Till
>> >> > >
>> >> > > On Fri, Feb 18, 2022 at 3:31 PM Galen Warren <
>> ga...@cvillewarrens.com
>> >> >
>> >> > > wrote:
>> >> > >
>> >> > > > The former.
>> >> > > >
>> >> > > > I think there's potential for confusion here because we're using
>> the
>> >> > > > word *function
>> >> > > > *in a couple of senses. One sense is a *stateful function*;
>> another
>> >> > sense
>> >> > > > is a *Go function*.
>> >> > > >
>> >> > > > What I'm looking to do is to put values in the Context so that
>> >> > downstream
>> >> > > > Go functions that receive the context can access those values.
>> Those
>> >> > > > downstream Go functions would be called during one invocation of
>> the
>> >> > > > stateful function.
>> >> > > >
>> >> > > > On Fri, Feb 18, 2022 at 6:48 AM Till Rohrmann <
>> trohrm...@apache.org
>> >> >
>> >> > > > wrote:
>> >> > > >
>> >> > > > > Hi Galen,
>> >> > > > >
>> >> > > > > Am I understanding it correctly, that you would like to set
>> some
>> >> > values
>> >> > > > in
>> >> > > > > the Context of function A that is then accessible in a
>> downstream
>> >> > call
>> >> > > of
>> >> > > > > function B? Or would you like to set a value that is accessible
>> >> once
>> >> > > > > function A is called again (w/ or w/o the same id)?
>> >> > > > >
>> >> > > > > Cheers,
>> >> > > > > Till
>> >> > > > >
>> >> > > > > On Thu, Feb 17, 2022 at 10:59 PM Galen Warren <
>> >> > ga...@cvillewarrens.com
>> >> > > >
>> >> > > > > wrote:
>> >> > > > >
>> >> > > > > > Also, a potentially simpler way to support this would be to
>> add
>> >> a
>> >> > > > > > SetContext method to the statefun.Context interface, and
>> have it
>> >> > > assign
>> >> > > > > the
>> >> > > > > > wrapped context. This would not require changes to the
>> function
>> >> > spec,
>> >> > > > or
>> >> > > > > > anything else, and would be more flexible.
>> >> > > > > >
>> >> > > > > > On Thu, Feb 17, 2022 at 1:05 PM Galen Warren <
>> >> > > ga...@cvillewarrens.com>
>> >> > > > > > wrote:
>> >> > > > > >
>> >> > > > > > > Thanks for the quick reply!
>> >> > > > > > >
>> >> > > > > > > What I'm trying to do is put some things into the context
>> so
>> >> that
>> >> > > > > they're
>> >> > > > > > > available in downstream calls, perhaps in methods with
>> pointer
>> >> > > > > receivers
>> >> > > > > > to
>> >> > > > > > > the function struct (MyFunc) but also perhaps in methods
>> that
>> >> are
>> >> > > > > further
>> >> > > > > > > downstream that don't have access to MyFunc. If I'm
>> >> understanding
>> >> > > > > > > correctly, your proposal would work for the former but not
>> the
>> >> > > > latter.
>> >> > > > > > >
>> >> > > > > > > An example would be to put a configured Logger into the
>> >> context
>> >> > > via a
>> >> > > > > > > WithLogger method (logging package -
>> knative.dev/pkg/logging
>> >> -
>> >> > > > > > pkg.go.dev
>> >> > > > > > > <https://pkg.go.dev/knative.dev/pkg/logging#WithLogger>)
>> and
>> >> > then
>> >> > > > pull
>> >> > > > > > it
>> >> > > > > > > out downstream via FromContext (logging package -
>> >> > > > > > knative.dev/pkg/logging
>> >> > > > > > > - pkg.go.dev <
>> >> > > https://pkg.go.dev/knative.dev/pkg/logging#FromContext
>> >> > > > > >).
>> >> > > > > > >
>> >> > > > > > >
>> >> > > > > > >
>> >> > > > > > >
>> >> > > > > > > On Wed, Feb 16, 2022 at 5:50 PM Seth Wiesman <
>> >> > sjwies...@gmail.com>
>> >> > > > > > wrote:
>> >> > > > > > >
>> >> > > > > > >> Hi Galen,
>> >> > > > > > >>
>> >> > > > > > >> No, that is not currently supported, the current idiomatic
>> >> way
>> >> > > would
>> >> > > > > be
>> >> > > > > > to
>> >> > > > > > >> pass those values to the struct implementing the Statefun
>> >> > > interface.
>> >> > > > > > >>
>> >> > > > > > >>
>> >> > > > > > >> type MyFunc struct { someRuntimeInfo string } func (m
>> >> *MyFunc)
>> >> > > > > > Invoke(ctx
>> >> > > > > > >> statefun.Context, message statefun.Message) error { } func
>> >> > main()
>> >> > > {
>> >> > > > > > >> builder
>> >> > > > > > >> := statefun.StatefulFunctionsBuilder()
>> >> > > > > > >> f := MyFunc { someRuntimeInfo: "runtime-provided" }
>> >> > > builder.WithSpec
>> >> > > > > > >> (statefun.StatefulFunctionSpec{ FunctionType:
>> >> > > statefun.TypeNameFrom(
>> >> > > > > > >> "example/my-func"), Function: f })
>> >> > > > > > >> http.Handle("/statefun", builder.AsHandler())
>> >> > > > > > >> _ = http.ListenAndServe(":8000", nil) }
>> >> > > > > > >>
>> >> > > > > > >> Would this work for you? Or what is the context (pun
>> >> intended)
>> >> > you
>> >> > > > are
>> >> > > > > > >> looking for?
>> >> > > > > > >>
>> >> > > > > > >> Seth
>> >> > > > > > >>
>> >> > > > > > >> On Wed, Feb 16, 2022 at 4:35 PM Galen Warren <
>> >> > > > ga...@cvillewarrens.com
>> >> > > > > >
>> >> > > > > > >> wrote:
>> >> > > > > > >>
>> >> > > > > > >> > When stateful functions are invoked, they are passed an
>> >> > instance
>> >> > > > of
>> >> > > > > > >> > statefun.Context, which wraps the context.Context
>> received
>> >> by
>> >> > > the
>> >> > > > > HTTP
>> >> > > > > > >> > request. Is there any way to customize that
>> context.Context
>> >> > to,
>> >> > > > say,
>> >> > > > > > >> hold
>> >> > > > > > >> > custom values, using ctx.WithValue()? I don't see a way
>> >> but I
>> >> > > > wanted
>> >> > > > > > to
>> >> > > > > > >> > ask.
>> >> > > > > > >> >
>> >> > > > > > >> > If not, would you be interested in a PR to add this
>> >> > > > functionality? A
>> >> > > > > > >> simple
>> >> > > > > > >> > way might be to add a property to StatefulFunctionSpec,
>> >> say:
>> >> > > > > > >> >
>> >> > > > > > >> > TransformContext func(ctx context.Context)
>> context.Context
>> >> > > > > > >> >
>> >> > > > > > >> > ... that, if supplied, would be called to create a
>> >> customized
>> >> > > > > context
>> >> > > > > > >> that
>> >> > > > > > >> > would be used downstream?
>> >> > > > > > >> >
>> >> > > > > > >> > Thanks.
>> >> > > > > > >> >
>> >> > > > > > >>
>> >> > > > > > >
>> >> > > > > >
>> >> > > > >
>> >> > > >
>> >> > >
>> >> >
>> >>
>> >
>>
>

Reply via email to