go-sdk icon indicating copy to clipboard operation
go-sdk copied to clipboard

[FEATURE] Implement transaction context

Open lukas-reining opened this issue 11 months ago • 5 comments

We should implement transaction context propagation

What is transaction context?

From the spec: Transaction context is a container for transaction-specific evaluation context (e.g. user id, user agent, IP). Transaction context can be set where specific data is available (e.g. an auth service or request handler) and by using the transaction context propagator it will automatically be applied to all flag evaluations within a transaction (e.g. a request or thread).

Transaction context has been added in the following PR: https://github.com/open-feature/spec/pull/227

Examples:

Implementation

The JS SDK implementation is implemented as a POC that is currently being hardened. https://github.com/open-feature/js-sdk/blob/main/packages/server/src/transaction-context/transaction-context.ts

Usage

An example usage for the JS SDK implementation of the feature is the usage for propagating HTTP request information in the NestJS SDK. https://github.com/open-feature/js-sdk/blob/main/packages/nest/src/evaluation-context-interceptor.ts#L31

lukas-reining avatar Feb 25 '24 15:02 lukas-reining

Is it expected that the user pass down the context? Because I'm not sure there's a trivial way in Go to have a context for a function call which isn't passed to it. It's possible to create a context.Context which has our TransactionContext as a value and require the user to use the context.Context when getting the feature flag:

// Creating the context
ctx := NewTransactionContext(context.Background(), map[string]int{"userID": 12345})
next(ctx)

// Using the context
client.BooleanValue(ctx, flag, defaultValue)

The implementation would be something like:

func NewTransactionContext(ctx context.Context, attributes map[string]interface{}) {
    return context.WithValue(ctx, "transactioncontext", attributes)
}

func (c *Client) BooleanValue(ctx context.Context, flag string, defaultValue bool, options ...Option) {
    transactionContext := ctx.Value("transactioncontext")
   ...
}

yardenlaif avatar Apr 02 '24 12:04 yardenlaif

@yardenlaif thanks for the interest in this issue :)

Is it expected that the user pass down the context?

Yes, context should be expected to be provided by the user. This maps with our current flag evaluation methods.

It's possible to create a context.Context which has our TransactionContext

+1 and we should expose it from openfeature api [1]

  // Derive transaction context
 openfeature.SetTransactionContext(ctx, value)

Regarding the key, use an empty struct instead of a string. For example, context.WithValue(ctx, key{}, "bla") where key is an empty struct to avoid hijacking.

[1] - https://github.com/open-feature/go-sdk?tab=readme-ov-file#usage

Kavindu-Dodan avatar Apr 02 '24 22:04 Kavindu-Dodan

Thanks @Kavindu-Dodan! @lukas-reining @thomaspoignant do you have anything to add?

beeme1mr avatar Apr 04 '24 17:04 beeme1mr

To me this looks like a plan @beeme1mr @Kavindu-Dodan @yardenlaif :)

lukas-reining avatar Apr 11 '24 15:04 lukas-reining

Yep, agreed. I think this is the idiom I would expect in Go.

toddbaert avatar Apr 17 '24 15:04 toddbaert