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

feat: context propagation #227

Merged
merged 18 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 53 additions & 2 deletions specification.json
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@
{
"id": "Conditional Requirement 3.2.2.4",
"machine_id": "conditional_requirement_3_2_2_4",
"content": "The API MUST have a a mechanism to manage `evaluation context` for an associated name.",
"content": "The API MUST have a mechanism to manage `evaluation context` for an associated name.",
"RFC 2119 keyword": "MUST",
"children": []
}
Expand All @@ -539,7 +539,7 @@
{
"id": "Requirement 3.2.3",
"machine_id": "requirement_3_2_3",
"content": "Evaluation context MUST be merged in the order: API (global; lowest precedence) - client - invocation - before hooks (highest precedence), with duplicate values being overwritten.",
"content": "Evaluation context MUST be merged in the order: API (global; lowest precedence) - transaction - client - invocation - before hooks (highest precedence), with duplicate values being overwritten.",
"RFC 2119 keyword": "MUST",
"children": []
},
Expand All @@ -565,6 +565,57 @@
}
]
},
{
"id": "Condition 3.3.1",
"machine_id": "condition_3_3_1",
"content": "The implementation uses the dynamic-context paradigm.",
"RFC 2119 keyword": null,
"children": [
{
"id": "Conditional Requirement 3.3.1.1",
"machine_id": "conditional_requirement_3_3_1_1",
"content": "The API MUST have a method for setting a `transaction context propagator`.",
"RFC 2119 keyword": "MUST",
"children": []
},
{
"id": "Conditional Requirement 3.3.1.2",
"machine_id": "conditional_requirement_3_3_1_2",
"content": "The API MUST have a method for setting the `evaluation context` of the `transaction context propagator`.",
"RFC 2119 keyword": "MUST",
"children": []
},
{
"id": "Conditional Requirement 3.3.1.3",
"machine_id": "conditional_requirement_3_3_1_3",
"content": "A `transaction context propagator` MUST have a method for setting the `evaluation context` of the current transaction.",
"RFC 2119 keyword": "MUST",
"children": []
},
{
"id": "Conditional Requirement 3.3.1.4",
"machine_id": "conditional_requirement_3_3_1_4",
"content": "A `transaction context propagator` MUST have a method for getting the `evaluation context` of the current transaction.",
"RFC 2119 keyword": "MUST",
"children": []
}
]
},
{
"id": "Condition 3.3.2",
"machine_id": "condition_3_3_2",
"content": "The implementation uses the static-context paradigm.",
"RFC 2119 keyword": null,
"children": [
{
"id": "Conditional Requirement 3.3.2.1",
"machine_id": "conditional_requirement_3_3_2_1",
"content": "The API MUST NOT have a method for setting a `transaction context propagator`.",
"RFC 2119 keyword": "MUST NOT",
"children": []
}
]
},
{
"id": "Requirement 4.1.1",
"machine_id": "requirement_4_1_1",
Expand Down
5 changes: 5 additions & 0 deletions specification/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ This document defines some terms that are used across this specification.
- [Provider](#provider)
- [Integration](#integration)
- [Evaluation Context](#evaluation-context)
- [Transaction Context Propagator](#transaction-context-propagator)
- [Evaluating Flag Values](#evaluating-flag-values)
- [Resolving Flag Values](#resolving-flag-values)
- [Flagging specifics](#flagging-specifics)
Expand Down Expand Up @@ -117,6 +118,10 @@ An SDK-compliant secondary function that is abstracted by the Feature Flag API,

Context object for flag evaluation, which may contain information about the runtime environment, details of the transport method encapsulating the flag evaluation, the host, the client, the subject (user), etc. This data may be used as a basis for differential evaluation of feature flags based on rules that can be defined in the flag system. Context data may be provided by merging static global context, arguments to flag evaluation, and implicit language-dependant state propagation mechanisms (thread-local storage, promise chains, continuations, etc).

### Transaction Context Propagator

An SDK-compliant implementation which stores and returns transaction specific evaluation context. A transaction can be something like a thread or web request.
lukas-reining marked this conversation as resolved.
Show resolved Hide resolved

### Evaluating Flag Values

The process of retrieving a feature flag value in it's entirety, including:
Expand Down
70 changes: 60 additions & 10 deletions specification/sections/03-evaluation-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,26 +88,28 @@ See [setting a provider](./01-flag-evaluation.md#setting-a-provider) for details

##### Conditional Requirement 3.2.2.4

> The API **MUST** have a a mechanism to manage `evaluation context` for an associated name.
> The API **MUST** have a mechanism to manage `evaluation context` for an associated name.

In the static-context paradigm, it must be possible to create and remove provider-specific context.
See [setting a provider](./01-flag-evaluation.md#setting-a-provider) for details.

#### Requirement 3.2.3

> Evaluation context **MUST** be merged in the order: API (global; lowest precedence) -> client -> invocation -> before hooks (highest precedence), with duplicate values being overwritten.
> Evaluation context **MUST** be merged in the order: API (global; lowest precedence) -> transaction -> client -> invocation -> before hooks (highest precedence), with duplicate values being overwritten.
lukas-reining marked this conversation as resolved.
Show resolved Hide resolved

Any fields defined in the client `evaluation context` will overwrite duplicate fields defined globally, and fields defined in the invocation `evaluation context` will overwrite duplicate fields defined globally or on the client. Any resulting `evaluation context` from a [before hook](./04-hooks.md#requirement-434) will overwrite duplicate fields defined globally, on the client, or in the invocation.

```mermaid
flowchart LR
global("API (global)")
client("Client")
invocation("Invocation")
hook("Before Hooks")
global --> client
client --> invocation
invocation --> hook
global("API (global)")
transaction("Transaction")
client("Client")
invocation("Invocation")
hook("Before Hooks")
global --> transaction
transaction --> client
client --> invocation
invocation --> hook
```

#### Condition 3.2.4
Expand All @@ -128,4 +130,52 @@ The SDK implementation must run the `on context changed` handler on all register

> When the `evaluation context` for a specific provider is set, the `on context changed` handler **MUST** only run on the associated provider.

The SDK implementation must run the `on context changed` handler only on the provider that is scoped to the mutated `evaluation context`.
The SDK implementation must run the `on context changed` handler only on the provider that is scoped to the mutated `evaluation context`.

### 3.3 Context Propagation

[![experimental](https://img.shields.io/static/v1?label=Status&message=experimental&color=orange)](https://github.com/open-feature/spec/tree/main/specification#experimental)

#### Condition 3.3.1

> The implementation uses the dynamic-context paradigm.

see: [dynamic-context paradigm](../glossary.md#dynamic-context-paradigm)

##### Conditional Requirement 3.3.1.1

> The API **MUST** have a method for setting a `transaction context propagator`.

If there already is a `transaction context propagator`, it is replaced with the new one.

##### Conditional Requirement 3.3.1.2

lukas-reining marked this conversation as resolved.
Show resolved Hide resolved
> The API **MUST** have a method for setting the `evaluation context` of the `transaction context propagator`.

lukas-reining marked this conversation as resolved.
Show resolved Hide resolved
If a `transaction context propagator` is set, this `evaluation context` must be supplied to it and so will be available during the current transaction.
lukas-reining marked this conversation as resolved.
Show resolved Hide resolved
This method can e.g. be used in a request handler to add request specific information to the `evaluation context`.

##### Conditional Requirement 3.3.1.3

> A `transaction context propagator` **MUST** have a method for setting the `evaluation context` of the current transaction.

A `transaction context propagator` is responsible for persisting context for the duration of a single transaction.
lukas-reining marked this conversation as resolved.
Show resolved Hide resolved
Typically, a transaction context propagator will propagate the context using a language-specific carrier such as [`ThreadLocal` (Java)](https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html), [`async hooks` (Node.js)](https://nodejs.org/api/async_hooks.html), [`Context` (Go)](https://pkg.go.dev/context) or another similar mechanism.

##### Conditional Requirement 3.3.1.4

> A `transaction context propagator` **MUST** have a method for getting the `evaluation context` of the current transaction.

lukas-reining marked this conversation as resolved.
Show resolved Hide resolved
This must be used by the SDK implementation when merging the context for evaluating a feature flag.

#### Condition 3.3.2

> The implementation uses the static-context paradigm.

see: [static-context paradigm](../glossary.md#static-context-paradigm)

##### Conditional Requirement 3.3.2.1

> The API **MUST NOT** have a method for setting a `transaction context propagator`.

lukas-reining marked this conversation as resolved.
Show resolved Hide resolved
In the static-context paradigm, context is global, so there should not be different context between transactions.
Loading