From 678e49280f7682711c4b8bde55a5c13ee441faac Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Tue, 2 Aug 2022 12:01:17 -0700 Subject: [PATCH 1/3] Remove context transformers. Add provider hooks Signed-off-by: Justin Abrahms --- specification.json | 19 +--------- specification/sections/02-providers.md | 52 +++++--------------------- specification/sections/04-hooks.md | 8 ++-- 3 files changed, 15 insertions(+), 64 deletions(-) diff --git a/specification.json b/specification.json index fd01be20..c2099e46 100644 --- a/specification.json +++ b/specification.json @@ -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.", + "content": "The provider interface MAY define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client.", "RFC 2119 keyword": "MAY", "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", @@ -465,7 +450,7 @@ { "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": [] }, diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index b38d5a8e..0b84ee09 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -111,59 +111,25 @@ ResolutionDetails resolveNumberValue(string flagKey, number defaultValue ResolutionDetails 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). +Feature flag management systems often need to transform the context structures the user provides or generally address lifecycle concerns. A `provider hook` exposes a mechanism for providers to register [`Hooks`](./04-hooks.md) to tap into various stages of the flag evaluation lifecycle. ##### 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 **MAY** define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client. - //... -} ``` - -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 { - +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()]; + } //... - } ``` diff --git a/specification/sections/04-hooks.md b/specification/sections/04-hooks.md index a7e6c7ac..cabc5b43 100644 --- a/specification/sections/04-hooks.md +++ b/specification/sections/04-hooks.md @@ -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 From 946be25b3cb8d7ac5eb826c9423e3615f21f3a1b Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Thu, 4 Aug 2022 08:33:31 -0700 Subject: [PATCH 2/3] Update based on review comments. Provider interface must add hook mechanism. Make wording clearer. Ensure Provider is listed alongside other hook registrars. Signed-off-by: Justin Abrahms --- specification.json | 6 +++--- specification/sections/02-providers.md | 4 ++-- specification/sections/04-hooks.md | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/specification.json b/specification.json index c2099e46..79e36301 100644 --- a/specification.json +++ b/specification.json @@ -266,8 +266,8 @@ { "id": "Requirement 2.10", "machine_id": "requirement_2_10", - "content": "The provider interface MAY define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client.", - "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": [] }, { @@ -443,7 +443,7 @@ { "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": [] }, diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index 0b84ee09..b69af541 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -113,11 +113,11 @@ ResolutionDetails resolveStructureValue(string flagKey, MyStruct defau #### Provider hooks -Feature flag management systems often need to transform the context structures the user provides or generally address lifecycle concerns. A `provider hook` exposes a mechanism for providers to register [`Hooks`](./04-hooks.md) to tap into various stages of the flag evaluation lifecycle. +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 `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client. +> The provider interface **MUST** define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client. ``` class MyProvider implements Provider { diff --git a/specification/sections/04-hooks.md b/specification/sections/04-hooks.md index cabc5b43..419e1d90 100644 --- a/specification/sections/04-hooks.md +++ b/specification/sections/04-hooks.md @@ -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()); From 9bc54eb37f79cbb523cb8d218211f1bf27092b6a Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Fri, 5 Aug 2022 10:46:04 -0700 Subject: [PATCH 3/3] Update specification/sections/02-providers.md Co-authored-by: Todd Baert Signed-off-by: Justin Abrahms --- specification.json | 2 +- specification/sections/02-providers.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specification.json b/specification.json index 79e36301..24c04dcb 100644 --- a/specification.json +++ b/specification.json @@ -266,7 +266,7 @@ { "id": "Requirement 2.10", "machine_id": "requirement_2_10", - "content": "The provider interface MUST define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client.", + "content": "The provider interface MUST define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the evaluation life-cycle.", "RFC 2119 keyword": "MUST", "children": [] }, diff --git a/specification/sections/02-providers.md b/specification/sections/02-providers.md index b69af541..9f59b8b6 100644 --- a/specification/sections/02-providers.md +++ b/specification/sections/02-providers.md @@ -117,7 +117,7 @@ A `provider hook` exposes a mechanism for `providers` to register [`hooks`](./04 ##### Requirement 2.10 -> The provider interface **MUST** define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the client. +> The provider interface **MUST** define a `provider hook` mechanism which can be optionally implemented in order to add `hook` instances to the evaluation life-cycle. ``` class MyProvider implements Provider {