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

Remove context transformers. Add provider hooks #119

Merged
merged 3 commits into from
Aug 5, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
23 changes: 4 additions & 19 deletions specification.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,25 +266,10 @@
{
"id": "Requirement 2.10",
"machine_id": "requirement_2_10",
"content": "The provider interface MAY define a `context transformer` method or function, which can be optionally implemented in order to transform the `evaluation context` prior to flag value resolution.",
"RFC 2119 keyword": "MAY",
"content": "The provider interface MUST define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client.",
"RFC 2119 keyword": "MUST",
"children": []
},
{
"id": "Condition 2.11",
"machine_id": "condition_2_11",
"content": "The implementation language supports generics (or an equivalent feature).",
"RFC 2119 keyword": null,
"children": [
{
"id": "Conditional Requirement 2.11.1",
"machine_id": "conditional_requirement_2_11_1",
"content": "If the implementation includes a `context transformer`, the provider SHOULD accept a generic argument (or use an equivalent language feature) indicating the type of the transformed context. If such type information is supplied, more accurate type information can be supplied in the flag resolution methods.",
"RFC 2119 keyword": "SHOULD",
"children": []
}
]
},
{
"id": "Requirement 3.1.1",
"machine_id": "requirement_3_1_1",
Expand Down Expand Up @@ -458,14 +443,14 @@
{
"id": "Requirement 4.4.1",
"machine_id": "requirement_4_4_1",
"content": "The API, Client and invocation MUST have a method for registering hooks which accepts `flag evaluation options`",
"content": "The API, Client, Provider, and invocation MUST have a method for registering hooks.",
"RFC 2119 keyword": "MUST",
"children": []
},
{
"id": "Requirement 4.4.2",
"machine_id": "requirement_4_4_2",
"content": "Hooks MUST be evaluated in the following order: - before: API, Client, Invocation - after: Invocation, Client, API - error (if applicable): Invocation, Client, API - finally: Invocation, Client, API",
"content": "Hooks MUST be evaluated in the following order: - before: API, Client, Invocation, Provider - after: Provider, Invocation, Client, API - error (if applicable): Provider, Invocation, Client, API - finally: Provider, Invocation, Client, API",
"RFC 2119 keyword": "MUST",
"children": []
},
Expand Down
52 changes: 9 additions & 43 deletions specification/sections/02-providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,59 +111,25 @@ ResolutionDetails<number> resolveNumberValue(string flagKey, number defaultValue
ResolutionDetails<MyStruct> resolveStructureValue(string flagKey, MyStruct defaultValue, context: EvaluationContext, options: FlagEvaluationOptions);
```

#### Context Transformation
#### Provider hooks

Feature flag management systems often define structures representing arbitrary contextual data pertaining to the runtime, user, or application. The context transformer defines a simple interface to transform the OpenFeature `evaluation context` to such a structure, mapping values appropriately.

See [evaluation context](./03-evaluation-context.md).
A `provider hook` exposes a mechanism for `providers` to register [`hooks`](./04-hooks.md) to tap into various stages of the flag evaluation lifecycle. As one example, feature flag management systems often need to transform the context structures the user provides.

##### Requirement 2.10

> The provider interface **MAY** define a `context transformer` method or function, which can be optionally implemented in order to transform the `evaluation context` prior to flag value resolution.

The OpenFeature `client` might apply the transformer function before passing the returned value (the `transformed context`) to the provider resolution methods, thus allowing the provider implementation to avoid implementing and calling such transformation logic repeatedly in flag value resolution methods.

```typescript
class MyProvider implements Provider {
//...

// implementation of context transformer
MyProviderContext transformContext(EvaluationContext context) {
return new MyProviderContext(context.email, context.ip, context.httpMethod);
}
> The provider interface **MUST** define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client.
justinabrahms marked this conversation as resolved.
Show resolved Hide resolved

//...
}
```

See [evaluation context](./03-evaluation-context.md), [flag evaluation](./01-flag-evaluation.md#flag-evaluation).

##### Condition 2.11

> The implementation language supports generics (or an equivalent feature).

###### Conditional Requirement 2.11.1

> If the implementation includes a `context transformer`, the provider **SHOULD** accept a generic argument (or use an equivalent language feature) indicating the type of the transformed context.
>
> If such type information is supplied, more accurate type information can be supplied in the flag resolution methods.

```typescript
// an example implementation in a language supporting interfaces, classes, and generics
// T represents a generic argument for the type of the transformed context
interface Provider<T> {

class MyProvider implements Provider {
//...

// context transformer signature
T transformContext(EvaluationContext context);

//...
private readonly hooks: Hook[] = [new MyProviderHook()];

// flag resolution methods context parameter type corresponds to class-generic
boolean resolveBooleanValue (string flagKey, boolean defaultValue, T transformedContext, EvaluationOptions options);
// ..or alternatively..
getProviderHooks(): Hook[] {
return [new MyProviderHook()];
}

//...

}
```
10 changes: 5 additions & 5 deletions specification/sections/04-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ EvaluationContext | void before(HookContext, HookHints);

#### Requirement 4.4.1

> The API, Client and invocation **MUST** have a method for registering hooks which accepts `flag evaluation options`
> The API, Client, Provider, and invocation **MUST** have a method for registering hooks.

```js
OpenFeature.addHooks(new Hook1());
Expand All @@ -132,10 +132,10 @@ client.getValue('my-flag', 'defaultValue', new Hook3());

> Hooks **MUST** be evaluated in the following order:
>
> - before: API, Client, Invocation
> - after: Invocation, Client, API
> - error (if applicable): Invocation, Client, API
> - finally: Invocation, Client, API
> - before: API, Client, Invocation, Provider
> - after: Provider, Invocation, Client, API
> - error (if applicable): Provider, Invocation, Client, API
> - finally: Provider, Invocation, Client, API

#### Requirement 4.4.3

Expand Down