From affa0b90c10944d560cefacf323437bac98a0e98 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 25 Apr 2023 14:03:16 -0400 Subject: [PATCH 01/24] feat: events Signed-off-by: Todd Baert --- specification.json | 42 ++++++++++++++++++++ specification/sections/05-events.md | 60 +++++++++++++++++++++++++++++ specification/types.md | 10 +++++ 3 files changed, 112 insertions(+) create mode 100644 specification/sections/05-events.md diff --git a/specification.json b/specification.json index e86e416b..b653f3d0 100644 --- a/specification.json +++ b/specification.json @@ -629,6 +629,48 @@ "content": "The hook MUST NOT alter the `hook hints` structure.", "RFC 2119 keyword": "MUST NOT", "children": [] + }, + { + "id": "Requirement 5.1.1", + "machine_id": "requirement_5_1_1", + "content": "The provider MAY define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_SHUTDOWN`.", + "RFC 2119 keyword": "MAY", + "children": [] + }, + { + "id": "Requirement 5.2.1", + "machine_id": "requirement_5_2_1", + "content": "The `client` MUST provide an `addHandler` function for attaching callbacks to `provider events`, which accepts event type(s) and a function to run when the associated event(s) occur.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 5.2.2", + "machine_id": "requirement_5_2_2", + "content": "If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 5.2.3", + "machine_id": "requirement_5_2_3", + "content": "If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers MUST run.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 5.2.3", + "machine_id": "requirement_5_2_3", + "content": "`PROVIDER_READY` handlers added after the provider is already in a ready state MUST run immediately.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 5.2.4", + "machine_id": "requirement_5_2_4", + "content": "Event handlers MUST persist across `provider` changes.", + "RFC 2119 keyword": "MUST", + "children": [] } ] } \ No newline at end of file diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md new file mode 100644 index 00000000..a0fff81d --- /dev/null +++ b/specification/sections/05-events.md @@ -0,0 +1,60 @@ +--- +title: Events +description: Specification defining event semantics +toc_max_heading_level: 4 +--- + +# 5. Events + +[![experimental](https://img.shields.io/static/v1?label=Status&message=experimental&color=orange)](https://github.com/open-feature/spec/tree/main/specification#experimental) + +## Overview + +`Events` allow consumers (_application integrator_, _application author_, _integration author_) to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. A provider may emit events or run a callback indicating that it received a certain event, optionally providing data associated with that event. Handlers registered on the client are then invoked with this data. + +### 5.1. Provider events + +#### Requirement 5.1.1 + +> The provider **MAY** define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_SHUTDOWN`. + +If available, native event-emitter or observable/observer language constructs can be used. + +see: [provider event types](./../types.md#provider-events) + +### 5.2. Event handlers + +#### Requirement 5.2.1 + +> The `client` **MUST** provide an `addHandler` function for attaching callbacks to `provider events`, which accepts event type(s) and a function to run when the associated event(s) occur. + +```java + // run the myOnReadyHandler function when the PROVIDER_READY event is fired + client.addHandler(ProviderEvents.Ready, MyClass::myOnReadyHandler); +``` + +see: [provider events](#51-provider-events) + +#### Requirement 5.2.2 + +> If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers **MUST** run. + +See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). + +#### Requirement 5.2.3 + +> If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers **MUST** run. + +See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). + +#### Requirement 5.2.3 + +> `PROVIDER_READY` handlers added after the provider is already in a ready state **MUST** run immediately. + +See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). + +#### Requirement 5.2.4 + +> Event handlers **MUST** persist across `provider` changes. + +Behavior of event handlers should be independent of the order of handler addition and provider configuration. \ No newline at end of file diff --git a/specification/types.md b/specification/types.md index b0ded0a9..bb21ca93 100644 --- a/specification/types.md +++ b/specification/types.md @@ -103,3 +103,13 @@ An enumeration of possible provider states. | NOT_READY | The provider has not been initialized. | | READY | The provider has been initialized, and is able to reliably resolve flag values. | | ERROR | The provider is initialized but is not able to reliably resolve flag values. | + +### Provider Events + +An enumeration of provider events. + +| Event | Explanation | +| ------------------------------ | ------------------------------------------------------------------------------------------- | +| PROVIDER_READY | The provider is ready to perform flag evaluations. | +| PROVIDER_ERROR | The provider signalled an error. | +| PROVIDER_CONFIGURATION_CHANGED | A change was made to the backend flag configuration. | From 339ea6095929edc3c9d3ee7d313aa98f0bcfa824 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 25 Apr 2023 14:10:14 -0400 Subject: [PATCH 02/24] fixup: fix numbering Signed-off-by: Todd Baert --- specification/sections/05-events.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index a0fff81d..13ab98b6 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -47,13 +47,13 @@ See [provider initialization](./02-providers.md#24-initialization) and [setting See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.3 +#### Requirement 5.2.4 > `PROVIDER_READY` handlers added after the provider is already in a ready state **MUST** run immediately. See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.4 +#### Requirement 5.2.5 > Event handlers **MUST** persist across `provider` changes. From 02e93d4f9663b0cf5c9eb453720d4d6108927527 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 25 Apr 2023 14:11:01 -0400 Subject: [PATCH 03/24] fixup: sync Signed-off-by: Todd Baert --- specification.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/specification.json b/specification.json index b653f3d0..1f81c3af 100644 --- a/specification.json +++ b/specification.json @@ -659,15 +659,15 @@ "children": [] }, { - "id": "Requirement 5.2.3", - "machine_id": "requirement_5_2_3", + "id": "Requirement 5.2.4", + "machine_id": "requirement_5_2_4", "content": "`PROVIDER_READY` handlers added after the provider is already in a ready state MUST run immediately.", "RFC 2119 keyword": "MUST", "children": [] }, { - "id": "Requirement 5.2.4", - "machine_id": "requirement_5_2_4", + "id": "Requirement 5.2.5", + "machine_id": "requirement_5_2_5", "content": "Event handlers MUST persist across `provider` changes.", "RFC 2119 keyword": "MUST", "children": [] From d872a1c2193593bea30c83f730c73895beaa3cfe Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Wed, 26 Apr 2023 11:07:29 -0400 Subject: [PATCH 04/24] fixup: remove shutdown Signed-off-by: Todd Baert --- specification.json | 2 +- specification/sections/05-events.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specification.json b/specification.json index 1f81c3af..c03761bf 100644 --- a/specification.json +++ b/specification.json @@ -633,7 +633,7 @@ { "id": "Requirement 5.1.1", "machine_id": "requirement_5_1_1", - "content": "The provider MAY define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_SHUTDOWN`.", + "content": "The provider MAY define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR` and `PROVIDER_CONFIGURATION_CHANGED`.", "RFC 2119 keyword": "MAY", "children": [] }, diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 13ab98b6..d03410e4 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -16,7 +16,7 @@ toc_max_heading_level: 4 #### Requirement 5.1.1 -> The provider **MAY** define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_SHUTDOWN`. +> The provider **MAY** define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR` and `PROVIDER_CONFIGURATION_CHANGED`. If available, native event-emitter or observable/observer language constructs can be used. From eaa2b0035054909a7dac6cbce413ca57aa62a14d Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Thu, 27 Apr 2023 14:28:53 -0400 Subject: [PATCH 05/24] fixup: additional clarity, event metadata Signed-off-by: Todd Baert --- specification.json | 33 +++++++++++++++++++++++----- specification/sections/04-hooks.md | 2 +- specification/sections/05-events.md | 34 ++++++++++++++++++++++++----- specification/types.md | 17 ++++++++++----- 4 files changed, 68 insertions(+), 18 deletions(-) diff --git a/specification.json b/specification.json index c03761bf..5a719a48 100644 --- a/specification.json +++ b/specification.json @@ -633,41 +633,62 @@ { "id": "Requirement 5.1.1", "machine_id": "requirement_5_1_1", - "content": "The provider MAY define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR` and `PROVIDER_CONFIGURATION_CHANGED`.", + "content": "The `provider` MAY define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `event metadata` payload.", "RFC 2119 keyword": "MAY", "children": [] }, + { + "id": "Requirement 5.1.2", + "machine_id": "requirement_5_1_2", + "content": "When the `provider` signals the occurrence of a particular `event`, the associated `client` `event handlers` MUST run.", + "RFC 2119 keyword": "MUST", + "children": [] + }, { "id": "Requirement 5.2.1", "machine_id": "requirement_5_2_1", - "content": "The `client` MUST provide an `addHandler` function for attaching callbacks to `provider events`, which accepts event type(s) and a function to run when the associated event(s) occur.", + "content": "The `client` MUST provide an `addHandler` function for attaching callbacks to `provider events`, which accepts event type(s) and a `event handler function`.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.2", "machine_id": "requirement_5_2_2", - "content": "If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run.", - "RFC 2119 keyword": "MUST", + "content": "The `event handler` function MAY accept a `event metadata` parameter.", + "RFC 2119 keyword": "MAY", "children": [] }, { "id": "Requirement 5.2.3", "machine_id": "requirement_5_2_3", - "content": "If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers MUST run.", + "content": "`PROVIDER_ERROR` events SHOULD populate the `event metadata`'s `error message` field.", + "RFC 2119 keyword": "SHOULD", + "children": [] + }, + { + "id": "Requirement 5.2.3", + "machine_id": "requirement_5_2_3", + "content": "If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.4", "machine_id": "requirement_5_2_4", - "content": "`PROVIDER_READY` handlers added after the provider is already in a ready state MUST run immediately.", + "content": "If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.5", "machine_id": "requirement_5_2_5", + "content": "`PROVIDER_READY` handlers added after the provider is already in a ready state MUST run immediately.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 5.2.6", + "machine_id": "requirement_5_2_6", "content": "Event handlers MUST persist across `provider` changes.", "RFC 2119 keyword": "MUST", "children": [] diff --git a/specification/sections/04-hooks.md b/specification/sections/04-hooks.md index b1e41e1f..9d64cc61 100644 --- a/specification/sections/04-hooks.md +++ b/specification/sections/04-hooks.md @@ -176,7 +176,7 @@ val = client.get_boolean_value('my-key', False, evaluation_options={ }) ``` -See: [Flag evaluation options](./01-flag-evaluation.md#) +see: [Flag evaluation options](./01-flag-evaluation.md#) #### Requirement 4.5.1 diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index d03410e4..c002867f 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -16,17 +16,33 @@ toc_max_heading_level: 4 #### Requirement 5.1.1 -> The provider **MAY** define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR` and `PROVIDER_CONFIGURATION_CHANGED`. +> The `provider` **MAY** define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `event metadata` payload. If available, native event-emitter or observable/observer language constructs can be used. -see: [provider event types](./../types.md#provider-events) +see: [provider event types](../types.md#provider-events), [`event metadata`](../types.md#event-metadata). + +#### Requirement 5.1.2 + +> When the `provider` signals the occurrence of a particular `event`, the associated `client` `event handlers` **MUST** run. + +If available, native event-emitter or observable/observer language constructs can be used. + +see: [provider event types](./../types.md#provider-events) and [event handlers](#52-event-handlers). + +#### Requirement 5.2.3 + +> `PROVIDER_ERROR` events **SHOULD** populate the `event metadata`'s `error message` field. + +The error message field should contain an informative message as to the nature of the error. + +See [event metadata](../types.md#event-metadata) ### 5.2. Event handlers #### Requirement 5.2.1 -> The `client` **MUST** provide an `addHandler` function for attaching callbacks to `provider events`, which accepts event type(s) and a function to run when the associated event(s) occur. +> The `client` **MUST** provide an `addHandler` function for attaching callbacks to `provider events`, which accepts event type(s) and a `event handler function`. ```java // run the myOnReadyHandler function when the PROVIDER_READY event is fired @@ -37,23 +53,29 @@ see: [provider events](#51-provider-events) #### Requirement 5.2.2 +> The `event handler` function **MAY** accept a `event metadata` parameter. + +see: [`event metadata`](../types.md#event-metadata) + +#### Requirement 5.2.3 + > If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers **MUST** run. See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.3 +#### Requirement 5.2.4 > If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers **MUST** run. See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.4 +#### Requirement 5.2.5 > `PROVIDER_READY` handlers added after the provider is already in a ready state **MUST** run immediately. See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.5 +#### Requirement 5.2.6 > Event handlers **MUST** persist across `provider` changes. diff --git a/specification/types.md b/specification/types.md index bb21ca93..8189729b 100644 --- a/specification/types.md +++ b/specification/types.md @@ -104,12 +104,19 @@ An enumeration of possible provider states. | READY | The provider has been initialized, and is able to reliably resolve flag values. | | ERROR | The provider is initialized but is not able to reliably resolve flag values. | +### Event Metadata + +A structure supporting the addition of arbitrary event data. +It supports definition of arbitrary properties, with keys of type `string`, and values of type `boolean`, `string`, or `number`. +It defines an `error message` field with a value of type `string`. + ### Provider Events An enumeration of provider events. -| Event | Explanation | -| ------------------------------ | ------------------------------------------------------------------------------------------- | -| PROVIDER_READY | The provider is ready to perform flag evaluations. | -| PROVIDER_ERROR | The provider signalled an error. | -| PROVIDER_CONFIGURATION_CHANGED | A change was made to the backend flag configuration. | +| Event | Explanation | +| ------------------------------ | --------------------------------------------------------------------------------------------------- | +| PROVIDER_READY | The provider is ready to perform flag evaluations. | +| PROVIDER_ERROR | The provider signalled an error. | +| PROVIDER_CONFIGURATION_CHANGED | A change was made to the backend flag configuration. | +| PROVIDER_STALE | The provider's cached state is not longer valid and may not be up-to-date with the source of truth. | From 0563cbd1b7cd01d5e9fbf81ec59569c9c7efa8c9 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Fri, 28 Apr 2023 11:12:35 -0400 Subject: [PATCH 06/24] fixup: error event metadata Signed-off-by: Todd Baert --- specification.json | 4 ++-- specification/sections/05-events.md | 8 ++++---- specification/types.md | 5 ++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/specification.json b/specification.json index 5a719a48..f70a8d1f 100644 --- a/specification.json +++ b/specification.json @@ -654,14 +654,14 @@ { "id": "Requirement 5.2.2", "machine_id": "requirement_5_2_2", - "content": "The `event handler` function MAY accept a `event metadata` parameter.", + "content": "The `event handler` function MAY accept a `event metadata` or `error event metadata` parameter.", "RFC 2119 keyword": "MAY", "children": [] }, { "id": "Requirement 5.2.3", "machine_id": "requirement_5_2_3", - "content": "`PROVIDER_ERROR` events SHOULD populate the `event metadata`'s `error message` field.", + "content": "`PROVIDER_ERROR` events SHOULD populate the `error event metadata`'s `error message` field.", "RFC 2119 keyword": "SHOULD", "children": [] }, diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index c002867f..3019354e 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -32,11 +32,11 @@ see: [provider event types](./../types.md#provider-events) and [event handlers]( #### Requirement 5.2.3 -> `PROVIDER_ERROR` events **SHOULD** populate the `event metadata`'s `error message` field. +> `PROVIDER_ERROR` events **SHOULD** populate the `error event metadata`'s `error message` field. The error message field should contain an informative message as to the nature of the error. -See [event metadata](../types.md#event-metadata) +See [event metadata](../types.md#error-event-metadata) ### 5.2. Event handlers @@ -53,9 +53,9 @@ see: [provider events](#51-provider-events) #### Requirement 5.2.2 -> The `event handler` function **MAY** accept a `event metadata` parameter. +> The `event handler` function **MAY** accept a `event metadata` or `error event metadata` parameter. -see: [`event metadata`](../types.md#event-metadata) +see: [`event metadata`](../types.md#event-metadata), [`error event metadata`](../types.md#error-event-metadata) #### Requirement 5.2.3 diff --git a/specification/types.md b/specification/types.md index 8189729b..0d44e6e8 100644 --- a/specification/types.md +++ b/specification/types.md @@ -108,7 +108,10 @@ An enumeration of possible provider states. A structure supporting the addition of arbitrary event data. It supports definition of arbitrary properties, with keys of type `string`, and values of type `boolean`, `string`, or `number`. -It defines an `error message` field with a value of type `string`. + +### Error Event Metadata + +An extension of the [`event metadata`](#event-metadata) type which defines an `error message` field with a value of type `string`. ### Provider Events From 9c372216daaa27d8879987bc9bb8f699d08b3df4 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Thu, 4 May 2023 08:59:52 -0400 Subject: [PATCH 07/24] fixup: numbering (thx anna) Signed-off-by: Todd Baert --- specification.json | 14 +++++++------- specification/sections/05-events.md | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/specification.json b/specification.json index f70a8d1f..7f331509 100644 --- a/specification.json +++ b/specification.json @@ -644,6 +644,13 @@ "RFC 2119 keyword": "MUST", "children": [] }, + { + "id": "Requirement 5.1.3", + "machine_id": "requirement_5_1_3", + "content": "`PROVIDER_ERROR` events SHOULD populate the `error event metadata`'s `error message` field.", + "RFC 2119 keyword": "SHOULD", + "children": [] + }, { "id": "Requirement 5.2.1", "machine_id": "requirement_5_2_1", @@ -658,13 +665,6 @@ "RFC 2119 keyword": "MAY", "children": [] }, - { - "id": "Requirement 5.2.3", - "machine_id": "requirement_5_2_3", - "content": "`PROVIDER_ERROR` events SHOULD populate the `error event metadata`'s `error message` field.", - "RFC 2119 keyword": "SHOULD", - "children": [] - }, { "id": "Requirement 5.2.3", "machine_id": "requirement_5_2_3", diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 3019354e..d6357c7e 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -30,7 +30,7 @@ If available, native event-emitter or observable/observer language constructs ca see: [provider event types](./../types.md#provider-events) and [event handlers](#52-event-handlers). -#### Requirement 5.2.3 +#### Requirement 5.1.3 > `PROVIDER_ERROR` events **SHOULD** populate the `error event metadata`'s `error message` field. From 857a09d08d6b0a1686653cba6e8196553b68eda0 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Thu, 4 May 2023 13:25:54 -0400 Subject: [PATCH 08/24] fixup: add handler error req Signed-off-by: Todd Baert --- specification.json | 11 +++++++++-- specification/sections/05-events.md | 8 ++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/specification.json b/specification.json index 7f331509..c7734f1d 100644 --- a/specification.json +++ b/specification.json @@ -651,6 +651,13 @@ "RFC 2119 keyword": "SHOULD", "children": [] }, + { + "id": "Requirement 5.1.4", + "machine_id": "requirement_5_1_4", + "content": "If a `handler functions` terminates abnormally, other event handlers MUST run.", + "RFC 2119 keyword": "MUST", + "children": [] + }, { "id": "Requirement 5.2.1", "machine_id": "requirement_5_2_1", @@ -661,8 +668,8 @@ { "id": "Requirement 5.2.2", "machine_id": "requirement_5_2_2", - "content": "The `event handler` function MAY accept a `event metadata` or `error event metadata` parameter.", - "RFC 2119 keyword": "MAY", + "content": "The `event handler` function MUST accept a `event metadata` or `error event metadata` parameter.", + "RFC 2119 keyword": "MUST", "children": [] }, { diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index d6357c7e..75a6c539 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -24,7 +24,7 @@ see: [provider event types](../types.md#provider-events), [`event metadata`](../ #### Requirement 5.1.2 -> When the `provider` signals the occurrence of a particular `event`, the associated `client` `event handlers` **MUST** run. +> When the `provider` signals the occurrence of a particular `event`, the associated `client` `event handlers` **MUST** run. If available, native event-emitter or observable/observer language constructs can be used. @@ -38,6 +38,10 @@ The error message field should contain an informative message as to the nature o See [event metadata](../types.md#error-event-metadata) +#### Requirement 5.1.4 + +> If a `handler functions` terminates abnormally, other event handlers **MUST** run. + ### 5.2. Event handlers #### Requirement 5.2.1 @@ -53,7 +57,7 @@ see: [provider events](#51-provider-events) #### Requirement 5.2.2 -> The `event handler` function **MAY** accept a `event metadata` or `error event metadata` parameter. +> The `event handler` function **MUST** accept a `event metadata` or `error event metadata` parameter. see: [`event metadata`](../types.md#event-metadata), [`error event metadata`](../types.md#error-event-metadata) From 4801e2c991828004363051c2d4577c2dff3f7c10 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Mon, 8 May 2023 15:49:55 -0400 Subject: [PATCH 09/24] fixup: add global events Signed-off-by: Todd Baert --- specification.json | 46 +++++++++++------ specification/sections/01-flag-evaluation.md | 2 +- specification/sections/05-events.md | 54 +++++++++++++------- specification/types.md | 34 ++++++++++-- 4 files changed, 96 insertions(+), 40 deletions(-) diff --git a/specification.json b/specification.json index c7734f1d..5c07da3c 100644 --- a/specification.json +++ b/specification.json @@ -45,7 +45,7 @@ { "id": "Requirement 1.1.5", "machine_id": "requirement_1_1_5", - "content": "The API MUST provide a function for retrieving the metadata field of the configured `provider`.", + "content": "The `API` MUST provide a function for retrieving the metadata field of the configured `provider`.", "RFC 2119 keyword": "MUST", "children": [] }, @@ -633,69 +633,83 @@ { "id": "Requirement 5.1.1", "machine_id": "requirement_5_1_1", - "content": "The `provider` MAY define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `event metadata` payload.", + "content": "The `provider` MAY define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `provider event details` payload.", "RFC 2119 keyword": "MAY", "children": [] }, { "id": "Requirement 5.1.2", "machine_id": "requirement_5_1_2", - "content": "When the `provider` signals the occurrence of a particular `event`, the associated `client` `event handlers` MUST run.", + "content": "When the `provider` signals the occurrence of a particular `event`, the associated `client` and `API` event handlers` MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.1.3", "machine_id": "requirement_5_1_3", - "content": "`PROVIDER_ERROR` events SHOULD populate the `error event metadata`'s `error message` field.", + "content": "`PROVIDER_ERROR` events SHOULD populate the `provider event details`'s `error message` field.", "RFC 2119 keyword": "SHOULD", "children": [] }, - { - "id": "Requirement 5.1.4", - "machine_id": "requirement_5_1_4", - "content": "If a `handler functions` terminates abnormally, other event handlers MUST run.", - "RFC 2119 keyword": "MUST", - "children": [] - }, { "id": "Requirement 5.2.1", "machine_id": "requirement_5_2_1", - "content": "The `client` MUST provide an `addHandler` function for attaching callbacks to `provider events`, which accepts event type(s) and a `event handler function`.", + "content": "The `client` MUST provide an `addHandler` function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.2", "machine_id": "requirement_5_2_2", - "content": "The `event handler` function MUST accept a `event metadata` or `error event metadata` parameter.", + "content": "The `API` MUST provide an `addHandler` function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.3", "machine_id": "requirement_5_2_3", - "content": "If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run.", + "content": "The `event details` MUST contain the `client name` associated with the event.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.4", "machine_id": "requirement_5_2_4", - "content": "If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers MUST run.", + "content": "The `event handler` function MUST accept a `event details` or `error event metadata` parameter.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.5", "machine_id": "requirement_5_2_5", - "content": "`PROVIDER_READY` handlers added after the provider is already in a ready state MUST run immediately.", + "content": "If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.6", "machine_id": "requirement_5_2_6", + "content": "If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers MUST run.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 5.2.7", + "machine_id": "requirement_5_2_7", + "content": "`PROVIDER_READY` handlers added after the provider is already in a ready state MUST run immediately.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 5.2.8", + "machine_id": "requirement_5_2_8", + "content": "If a `handler functions` terminates abnormally, other event handlers MUST run.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 5.2.9", + "machine_id": "requirement_5_2_9", "content": "Event handlers MUST persist across `provider` changes.", "RFC 2119 keyword": "MUST", "children": [] diff --git a/specification/sections/01-flag-evaluation.md b/specification/sections/01-flag-evaluation.md index 47421e9d..207c9b6a 100644 --- a/specification/sections/01-flag-evaluation.md +++ b/specification/sections/01-flag-evaluation.md @@ -72,7 +72,7 @@ See [hooks](./04-hooks.md) for details. #### Requirement 1.1.5 -> The API **MUST** provide a function for retrieving the metadata field of the configured `provider`. +> The `API` **MUST** provide a function for retrieving the metadata field of the configured `provider`. ```typescript // example provider accessor diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 75a6c539..e7faa3cc 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -16,70 +16,86 @@ toc_max_heading_level: 4 #### Requirement 5.1.1 -> The `provider` **MAY** define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `event metadata` payload. +> The `provider` **MAY** define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `provider event details` payload. If available, native event-emitter or observable/observer language constructs can be used. -see: [provider event types](../types.md#provider-events), [`event metadata`](../types.md#event-metadata). +see: [provider event types](../types.md#provider-events), [`event details`](../types.md#provider-event-details). #### Requirement 5.1.2 -> When the `provider` signals the occurrence of a particular `event`, the associated `client` `event handlers` **MUST** run. - -If available, native event-emitter or observable/observer language constructs can be used. +> When the `provider` signals the occurrence of a particular `event`, the associated `client` and `API` event handlers` **MUST** run. see: [provider event types](./../types.md#provider-events) and [event handlers](#52-event-handlers). #### Requirement 5.1.3 -> `PROVIDER_ERROR` events **SHOULD** populate the `error event metadata`'s `error message` field. +> `PROVIDER_ERROR` events **SHOULD** populate the `provider event details`'s `error message` field. The error message field should contain an informative message as to the nature of the error. -See [event metadata](../types.md#error-event-metadata) - -#### Requirement 5.1.4 - -> If a `handler functions` terminates abnormally, other event handlers **MUST** run. +See [event metadata](../types.md#error-event-details) ### 5.2. Event handlers #### Requirement 5.2.1 -> The `client` **MUST** provide an `addHandler` function for attaching callbacks to `provider events`, which accepts event type(s) and a `event handler function`. +> The `client` **MUST** provide an `addHandler` function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`. ```java - // run the myOnReadyHandler function when the PROVIDER_READY event is fired - client.addHandler(ProviderEvents.Ready, MyClass::myOnReadyHandler); + // run the myClientOnReadyHandler function when the PROVIDER_READY event is fired + client.addHandler(ProviderEvents.Ready, MyClass::myClientOnReadyHandler); ``` see: [provider events](#51-provider-events) #### Requirement 5.2.2 -> The `event handler` function **MUST** accept a `event metadata` or `error event metadata` parameter. +> The `API` **MUST** provide an `addHandler` function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`. + +```java + // run the myGlobalErrorHandler function when the PROVIDER_READY event is fired + OpenFeature.addHandler(ProviderEvents.Error, MyClass::myGlobalErrorHandler); +``` -see: [`event metadata`](../types.md#event-metadata), [`error event metadata`](../types.md#error-event-metadata) +see: [provider events](#51-provider-events), [`provider event types`](../types.md#provider-events) #### Requirement 5.2.3 +> The `event details` **MUST** contain the `client name` associated with the event. + +The `client name` indicates the client/provider with which the event is associated. +This is particularly relevant for `event handler functions` which are attached to the `API`, not a particular client. + +#### Requirement 5.2.4 + +> The `event handler` function **MUST** accept a `event details` or `error event metadata` parameter. + +see: [`event details`](../types.md#event-details), [`error event metadata`](../types.md#error-event-details) + +#### Requirement 5.2.5 + > If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers **MUST** run. See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.4 +#### Requirement 5.2.6 > If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers **MUST** run. See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.5 +#### Requirement 5.2.7 > `PROVIDER_READY` handlers added after the provider is already in a ready state **MUST** run immediately. See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.6 +#### Requirement 5.2.8 + +> If a `handler functions` terminates abnormally, other event handlers **MUST** run. + +#### Requirement 5.2.9 > Event handlers **MUST** persist across `provider` changes. diff --git a/specification/types.md b/specification/types.md index 0d44e6e8..d4755880 100644 --- a/specification/types.md +++ b/specification/types.md @@ -104,15 +104,41 @@ An enumeration of possible provider states. | READY | The provider has been initialized, and is able to reliably resolve flag values. | | ERROR | The provider is initialized but is not able to reliably resolve flag values. | +### Provider Event Details + +A structure defining a provider event payload, including: + +- flags changed (string[], optional) +- event metadata ([event metadata](#event-metadata)) + +### Provider Error Event Details + +A structure defining a provider error event payload, including: + +- error message (string, required) +- event metadata ([flag metadata](#event-metadata)) + +### Event Details + +A structure defining an event payload, including: + +- client name (string, required) +- flags changed (string[], optional) +- event metadata ([event metadata](#event-metadata)) + +### Error Event Details + +A structure defining an error event payload, including: + +- client name (string, required) +- error message (string, required) +- event metadata ([flag metadata](#event-metadata)) + ### Event Metadata A structure supporting the addition of arbitrary event data. It supports definition of arbitrary properties, with keys of type `string`, and values of type `boolean`, `string`, or `number`. -### Error Event Metadata - -An extension of the [`event metadata`](#event-metadata) type which defines an `error message` field with a value of type `string`. - ### Provider Events An enumeration of provider events. From 25c0f21a8b9b048ea9ef8e6bc9d5c421e4148ec8 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Mon, 8 May 2023 16:27:20 -0400 Subject: [PATCH 10/24] fixup: spelling Signed-off-by: Todd Baert --- specification.json | 2 +- specification/sections/05-events.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specification.json b/specification.json index 5c07da3c..c81e61d5 100644 --- a/specification.json +++ b/specification.json @@ -633,7 +633,7 @@ { "id": "Requirement 5.1.1", "machine_id": "requirement_5_1_1", - "content": "The `provider` MAY define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `provider event details` payload.", + "content": "The `provider` MAY define a mechanism for signaling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `provider event details` payload.", "RFC 2119 keyword": "MAY", "children": [] }, diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index e7faa3cc..d995231b 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -16,7 +16,7 @@ toc_max_heading_level: 4 #### Requirement 5.1.1 -> The `provider` **MAY** define a mechanism for signalling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `provider event details` payload. +> The `provider` **MAY** define a mechanism for signaling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `provider event details` payload. If available, native event-emitter or observable/observer language constructs can be used. From 4068982d90fe060ac16c8032325aa322c77b2d7d Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 9 May 2023 10:50:01 -0400 Subject: [PATCH 11/24] Update specification/types.md Co-authored-by: Pete Hodgson Signed-off-by: Todd Baert --- specification/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/types.md b/specification/types.md index d4755880..8f8e27b5 100644 --- a/specification/types.md +++ b/specification/types.md @@ -132,7 +132,7 @@ A structure defining an error event payload, including: - client name (string, required) - error message (string, required) -- event metadata ([flag metadata](#event-metadata)) +- event metadata ([event metadata](#event-metadata)) ### Event Metadata From cf4932fb42f129e809ac504ba33b95d6471b9419 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 9 May 2023 11:13:56 -0400 Subject: [PATCH 12/24] fixup: more clarity Break out new section for event handlers and initialization, add more non-normative text Signed-off-by: Todd Baert --- specification.json | 22 +++++++++--------- specification/sections/05-events.md | 35 +++++++++++++++++++---------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/specification.json b/specification.json index c81e61d5..a974f297 100644 --- a/specification.json +++ b/specification.json @@ -682,35 +682,35 @@ { "id": "Requirement 5.2.5", "machine_id": "requirement_5_2_5", - "content": "If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run.", + "content": "If a `handler functions` terminates abnormally, other event handlers MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.6", "machine_id": "requirement_5_2_6", - "content": "If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers MUST run.", + "content": "Event handlers MUST persist across `provider` changes.", "RFC 2119 keyword": "MUST", "children": [] }, { - "id": "Requirement 5.2.7", - "machine_id": "requirement_5_2_7", - "content": "`PROVIDER_READY` handlers added after the provider is already in a ready state MUST run immediately.", + "id": "Requirement 5.3.1", + "machine_id": "requirement_5_3_1", + "content": "If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { - "id": "Requirement 5.2.8", - "machine_id": "requirement_5_2_8", - "content": "If a `handler functions` terminates abnormally, other event handlers MUST run.", + "id": "Requirement 5.3.2", + "machine_id": "requirement_5_3_2", + "content": "If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { - "id": "Requirement 5.2.9", - "machine_id": "requirement_5_2_9", - "content": "Event handlers MUST persist across `provider` changes.", + "id": "Requirement 5.3.3", + "machine_id": "requirement_5_3_3", + "content": "`PROVIDER_READY` handlers attached after the provider is already in a ready state MUST run immediately.", "RFC 2119 keyword": "MUST", "children": [] } diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index d995231b..195defff 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -12,6 +12,8 @@ toc_max_heading_level: 4 `Events` allow consumers (_application integrator_, _application author_, _integration author_) to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. A provider may emit events or run a callback indicating that it received a certain event, optionally providing data associated with that event. Handlers registered on the client are then invoked with this data. +The data that providers supply in event payloads may include a list of `flag keys` changed, error messages, and possibly updated flag values. + ### 5.1. Provider events #### Requirement 5.1.1 @@ -75,28 +77,37 @@ see: [`event details`](../types.md#event-details), [`error event metadata`](../t #### Requirement 5.2.5 -> If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers **MUST** run. - -See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). +> If a `handler functions` terminates abnormally, other event handlers **MUST** run. #### Requirement 5.2.6 -> If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers **MUST** run. +> Event handlers **MUST** persist across `provider` changes. -See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). +Behavior of event handlers should be independent of the order of handler addition and provider configuration. + +### Event handlers and initialization -#### Requirement 5.2.7 +Though providers themselves need not implement events, the `flag evaluation API` uses events to convey relevant state changes during configuration and initialization. +_Application authors_ and _application integrators_ use these events to wait for proper initialization of the SDK and provider and to do basic monitoring. -> `PROVIDER_READY` handlers added after the provider is already in a ready state **MUST** run immediately. +#### Requirement 5.3.1 + +> If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers **MUST** run. See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). -#### Requirement 5.2.8 +#### Requirement 5.3.2 -> If a `handler functions` terminates abnormally, other event handlers **MUST** run. +> If the provider's `initialize` function terminates abnormally, `PROVIDER_ERROR` handlers **MUST** run. -#### Requirement 5.2.9 +A failed initialization could represent an unrecoverable error, such as bad credentials or a missing file. +If a failed initialization could also represent a transient error. +A provider which maintains a persistent connection to a remote `flag management system` may attempt to reconnect, and emit `PROVIDER_READY` after a failed initialization. -> Event handlers **MUST** persist across `provider` changes. +See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). + +#### Requirement 5.3.3 -Behavior of event handlers should be independent of the order of handler addition and provider configuration. \ No newline at end of file +> `PROVIDER_READY` handlers attached after the provider is already in a ready state **MUST** run immediately. + +See [provider initialization](./02-providers.md#24-initialization) and [setting a provider](./01-flag-evaluation.md#setting-a-provider). From b072502395f15f9572a919caa4ff87f3b10ef9ce Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 9 May 2023 11:17:06 -0400 Subject: [PATCH 13/24] fixup: client shutdown Signed-off-by: Todd Baert --- specification.json | 9 ++++++++- specification/sections/01-flag-evaluation.md | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/specification.json b/specification.json index a974f297..6dfdb2c7 100644 --- a/specification.json +++ b/specification.json @@ -230,7 +230,14 @@ { "id": "Requirement 1.6.1", "machine_id": "requirement_1_6_1", - "content": "The API MUST define a `shutdown` function, which, when called, must call the respective `shutdown` function on the active provider.", + "content": "The API MUST define a `shutdown` function which, when called, must call the respective `shutdown` function on the active provider.", + "RFC 2119 keyword": "MUST", + "children": [] + }, + { + "id": "Requirement 1.6.2", + "machine_id": "requirement_1_6_2", + "content": "The client MUST define a `shutdown` function which, when called, removes all the event handlers associated with that client.", "RFC 2119 keyword": "MUST", "children": [] }, diff --git a/specification/sections/01-flag-evaluation.md b/specification/sections/01-flag-evaluation.md index 207c9b6a..e3662793 100644 --- a/specification/sections/01-flag-evaluation.md +++ b/specification/sections/01-flag-evaluation.md @@ -274,9 +274,16 @@ See [hooks](./04-hooks.md) for details. #### Requirement 1.6.1 -> The API **MUST** define a `shutdown` function, which, when called, must call the respective `shutdown` function on the active provider. +> The API **MUST** define a `shutdown` function which, when called, must call the respective `shutdown` function on the active provider. The precise name of this function is not prescribed by this specification, but should be defined be the SDK. Relevant language idioms should be considered when choosing the name for this function, in accordance with the resource-disposal semantics of the language in question. see: [`shutdown`](./02-providers.md#25-shutdown) + +#### Requirement 1.6.2 + +> The client **MUST** define a `shutdown` function which, when called, removes all the event handlers associated with that client. + +The precise name of this function is not prescribed by this specification, but should be defined be the SDK. +Relevant language idioms should be considered when choosing the name for this function, in accordance with the resource-disposal semantics of the language in question. From e09a20ae9906a05e1aed8ca265ca7ceb4e3d7e21 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 9 May 2023 11:28:59 -0400 Subject: [PATCH 14/24] fixup: simplify event details Signed-off-by: Todd Baert --- specification.json | 2 +- specification/sections/05-events.md | 4 ++-- specification/types.md | 17 ++--------------- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/specification.json b/specification.json index 6dfdb2c7..c2b1ccce 100644 --- a/specification.json +++ b/specification.json @@ -682,7 +682,7 @@ { "id": "Requirement 5.2.4", "machine_id": "requirement_5_2_4", - "content": "The `event handler` function MUST accept a `event details` or `error event metadata` parameter.", + "content": "The `event handler` function MUST accept a `event details` parameter.", "RFC 2119 keyword": "MUST", "children": [] }, diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 195defff..96f9a084 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -71,9 +71,9 @@ This is particularly relevant for `event handler functions` which are attached t #### Requirement 5.2.4 -> The `event handler` function **MUST** accept a `event details` or `error event metadata` parameter. +> The `event handler` function **MUST** accept a `event details` parameter. -see: [`event details`](../types.md#event-details), [`error event metadata`](../types.md#error-event-details) +see: [`event details`](../types.md#event-details) #### Requirement 5.2.5 diff --git a/specification/types.md b/specification/types.md index 8f8e27b5..5f74880a 100644 --- a/specification/types.md +++ b/specification/types.md @@ -109,29 +109,16 @@ An enumeration of possible provider states. A structure defining a provider event payload, including: - flags changed (string[], optional) +- message (string, optional) - event metadata ([event metadata](#event-metadata)) -### Provider Error Event Details - -A structure defining a provider error event payload, including: - -- error message (string, required) -- event metadata ([flag metadata](#event-metadata)) - ### Event Details A structure defining an event payload, including: - client name (string, required) - flags changed (string[], optional) -- event metadata ([event metadata](#event-metadata)) - -### Error Event Details - -A structure defining an error event payload, including: - -- client name (string, required) -- error message (string, required) +- message (string, optional) - event metadata ([event metadata](#event-metadata)) ### Event Metadata From 7cba5ba24c1783231b3d6e468373554bcf43723c Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 9 May 2023 12:30:50 -0400 Subject: [PATCH 15/24] fixup: add specific point about event scoping Signed-off-by: Todd Baert --- specification.json | 9 ++++++++- specification/sections/05-events.md | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/specification.json b/specification.json index c2b1ccce..39a58bb5 100644 --- a/specification.json +++ b/specification.json @@ -647,13 +647,20 @@ { "id": "Requirement 5.1.2", "machine_id": "requirement_5_1_2", - "content": "When the `provider` signals the occurrence of a particular `event`, the associated `client` and `API` event handlers` MUST run.", + "content": "When a `provider` signals the occurrence of a particular `event`, the associated `client` and `API` `event handlers` MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.1.3", "machine_id": "requirement_5_1_3", + "content": "When a `provider` signals the occurrence of a particular `event`, `event handlers` on clients which are not associated with that provider MUST NOT run.", + "RFC 2119 keyword": "MUST NOT", + "children": [] + }, + { + "id": "Requirement 5.1.4", + "machine_id": "requirement_5_1_4", "content": "`PROVIDER_ERROR` events SHOULD populate the `provider event details`'s `error message` field.", "RFC 2119 keyword": "SHOULD", "children": [] diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 96f9a084..9be1eb16 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -10,7 +10,7 @@ toc_max_heading_level: 4 ## Overview -`Events` allow consumers (_application integrator_, _application author_, _integration author_) to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. A provider may emit events or run a callback indicating that it received a certain event, optionally providing data associated with that event. Handlers registered on the client are then invoked with this data. +`Events` allow consumers (_application integrator_, _application author_, _integration author_) to react to state changes in the provider or underlying flag management system, such as flag definition changes, provider readiness, or error conditions. A provider may emit events or run a callback indicating that it received a certain event, optionally providing data associated with that event. Handlers registered on the `client` or the global `API` are then invoked with this data. The data that providers supply in event payloads may include a list of `flag keys` changed, error messages, and possibly updated flag values. @@ -26,12 +26,20 @@ see: [provider event types](../types.md#provider-events), [`event details`](../t #### Requirement 5.1.2 -> When the `provider` signals the occurrence of a particular `event`, the associated `client` and `API` event handlers` **MUST** run. +> When a `provider` signals the occurrence of a particular `event`, the associated `client` and `API` `event handlers` **MUST** run. see: [provider event types](./../types.md#provider-events) and [event handlers](#52-event-handlers). #### Requirement 5.1.3 +> When a `provider` signals the occurrence of a particular `event`, `event handlers` on clients which are not associated with that provider **MUST NOT** run. + +Providers bound to a named client constitute their own scope events scope. + +see: [setting a provider](./01-flag-evaluation.md#setting-a-provider) + +#### Requirement 5.1.4 + > `PROVIDER_ERROR` events **SHOULD** populate the `provider event details`'s `error message` field. The error message field should contain an informative message as to the nature of the error. From c47b03fff1056efbc47b377e42fdf27d3ffe8bfa Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 9 May 2023 13:16:00 -0400 Subject: [PATCH 16/24] fixup: add mermaid diagram Signed-off-by: Todd Baert --- specification/sections/05-events.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 9be1eb16..21c471af 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -14,6 +14,14 @@ toc_max_heading_level: 4 The data that providers supply in event payloads may include a list of `flag keys` changed, error messages, and possibly updated flag values. +```mermaid +graph + P(Provider) -->|emit event| A[API] + A -->|run handlers| AH(API event handlers) + A --> C[Client] + C -->|run handlers| CH(Client event handlers) +``` + ### 5.1. Provider events #### Requirement 5.1.1 From 5bc1c52c752a46b4503d541dd2e7953e6be5350b Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 9 May 2023 13:21:26 -0400 Subject: [PATCH 17/24] fixup: mark API global in diagram Signed-off-by: Todd Baert --- specification/sections/05-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 21c471af..7da55fb2 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -17,7 +17,7 @@ The data that providers supply in event payloads may include a list of `flag key ```mermaid graph P(Provider) -->|emit event| A[API] - A -->|run handlers| AH(API event handlers) + A -->|run handlers| AH("API (global) event handlers") A --> C[Client] C -->|run handlers| CH(Client event handlers) ``` From 8da59ab86ed6b57264e507f31318489b69a803c1 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Tue, 9 May 2023 13:24:59 -0400 Subject: [PATCH 18/24] fixup: more clarity on events and init Signed-off-by: Todd Baert --- specification/sections/05-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 7da55fb2..ee8737ec 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -104,7 +104,7 @@ Behavior of event handlers should be independent of the order of handler additio ### Event handlers and initialization Though providers themselves need not implement events, the `flag evaluation API` uses events to convey relevant state changes during configuration and initialization. -_Application authors_ and _application integrators_ use these events to wait for proper initialization of the SDK and provider and to do basic monitoring. +_Application authors_ and _application integrators_ use these events to wait for proper initialization of the SDK and provider and to do basic monitoring and error handling. #### Requirement 5.3.1 From d0e72515bd2b43dfd1aa9319a9484ecb6e2b9b28 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Fri, 12 May 2023 09:23:13 -0400 Subject: [PATCH 19/24] fixup: handler name flexibility Signed-off-by: Todd Baert --- specification.json | 4 ++-- specification/sections/05-events.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/specification.json b/specification.json index 39a58bb5..75648c85 100644 --- a/specification.json +++ b/specification.json @@ -668,14 +668,14 @@ { "id": "Requirement 5.2.1", "machine_id": "requirement_5_2_1", - "content": "The `client` MUST provide an `addHandler` function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`.", + "content": "The `client` MUST provide a function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.2", "machine_id": "requirement_5_2_2", - "content": "The `API` MUST provide an `addHandler` function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`.", + "content": "The `API` MUST provide a function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`.", "RFC 2119 keyword": "MUST", "children": [] }, diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index ee8737ec..df20feb0 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -58,7 +58,7 @@ See [event metadata](../types.md#error-event-details) #### Requirement 5.2.1 -> The `client` **MUST** provide an `addHandler` function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`. +> The `client` **MUST** provide a function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`. ```java // run the myClientOnReadyHandler function when the PROVIDER_READY event is fired @@ -69,7 +69,7 @@ see: [provider events](#51-provider-events) #### Requirement 5.2.2 -> The `API` **MUST** provide an `addHandler` function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`. +> The `API` **MUST** provide a function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`. ```java // run the myGlobalErrorHandler function when the PROVIDER_READY event is fired From a4e70ab3e89bdb23e145cd73e14bdce11022417c Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Fri, 12 May 2023 09:23:49 -0400 Subject: [PATCH 20/24] fixup: no client shutdown, event handler removal Signed-off-by: Todd Baert --- specification.json | 14 +++++++------- specification/sections/01-flag-evaluation.md | 7 ------- specification/sections/05-events.md | 4 ++++ 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/specification.json b/specification.json index 75648c85..da609025 100644 --- a/specification.json +++ b/specification.json @@ -234,13 +234,6 @@ "RFC 2119 keyword": "MUST", "children": [] }, - { - "id": "Requirement 1.6.2", - "machine_id": "requirement_1_6_2", - "content": "The client MUST define a `shutdown` function which, when called, removes all the event handlers associated with that client.", - "RFC 2119 keyword": "MUST", - "children": [] - }, { "id": "Requirement 2.1.1", "machine_id": "requirement_2_1_1", @@ -707,6 +700,13 @@ "RFC 2119 keyword": "MUST", "children": [] }, + { + "id": "Requirement 5.2.7", + "machine_id": "requirement_5_2_7", + "content": "The `API` and `client` MUST provide a function allowing the removal of event handlers.", + "RFC 2119 keyword": "MUST", + "children": [] + }, { "id": "Requirement 5.3.1", "machine_id": "requirement_5_3_1", diff --git a/specification/sections/01-flag-evaluation.md b/specification/sections/01-flag-evaluation.md index e3662793..1f0107fb 100644 --- a/specification/sections/01-flag-evaluation.md +++ b/specification/sections/01-flag-evaluation.md @@ -280,10 +280,3 @@ The precise name of this function is not prescribed by this specification, but s Relevant language idioms should be considered when choosing the name for this function, in accordance with the resource-disposal semantics of the language in question. see: [`shutdown`](./02-providers.md#25-shutdown) - -#### Requirement 1.6.2 - -> The client **MUST** define a `shutdown` function which, when called, removes all the event handlers associated with that client. - -The precise name of this function is not prescribed by this specification, but should be defined be the SDK. -Relevant language idioms should be considered when choosing the name for this function, in accordance with the resource-disposal semantics of the language in question. diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index df20feb0..92a32606 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -101,6 +101,10 @@ see: [`event details`](../types.md#event-details) Behavior of event handlers should be independent of the order of handler addition and provider configuration. +#### Requirement 5.2.7 + +> The `API` and `client` **MUST** provide a function allowing the removal of event handlers. + ### Event handlers and initialization Though providers themselves need not implement events, the `flag evaluation API` uses events to convey relevant state changes during configuration and initialization. From f2c9367b23e42640af18166e04167d2f27bf3cf8 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Fri, 12 May 2023 13:36:09 -0400 Subject: [PATCH 21/24] fixup: loosen event handler def Signed-off-by: Todd Baert --- specification.json | 14 ++++++------- specification/sections/05-events.md | 31 +++++++++++++++-------------- specification/types.md | 5 +++++ 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/specification.json b/specification.json index da609025..937273aa 100644 --- a/specification.json +++ b/specification.json @@ -633,21 +633,21 @@ { "id": "Requirement 5.1.1", "machine_id": "requirement_5_1_1", - "content": "The `provider` MAY define a mechanism for signaling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `provider event details` payload.", + "content": "The `provider` MAY define a mechanism for signaling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with a `provider event details` payload.", "RFC 2119 keyword": "MAY", "children": [] }, { "id": "Requirement 5.1.2", "machine_id": "requirement_5_1_2", - "content": "When a `provider` signals the occurrence of a particular `event`, the associated `client` and `API` `event handlers` MUST run.", + "content": "When a `provider` signals the occurrence of a particular `event`, the associated `client` and `API` event handlers MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.1.3", "machine_id": "requirement_5_1_3", - "content": "When a `provider` signals the occurrence of a particular `event`, `event handlers` on clients which are not associated with that provider MUST NOT run.", + "content": "When a `provider` signals the occurrence of a particular `event`, event handlers on clients which are not associated with that provider MUST NOT run.", "RFC 2119 keyword": "MUST NOT", "children": [] }, @@ -661,14 +661,14 @@ { "id": "Requirement 5.2.1", "machine_id": "requirement_5_2_1", - "content": "The `client` MUST provide a function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`.", + "content": "The `client` MUST provide a function for associating `handler functions` with a particular `provider event type`.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.2", "machine_id": "requirement_5_2_2", - "content": "The `API` MUST provide a function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`.", + "content": "The `API` MUST provide a function for associating `handler functions` with a particular `provider event type`.", "RFC 2119 keyword": "MUST", "children": [] }, @@ -682,14 +682,14 @@ { "id": "Requirement 5.2.4", "machine_id": "requirement_5_2_4", - "content": "The `event handler` function MUST accept a `event details` parameter.", + "content": "The `handler function` MUST accept a `event details` parameter.", "RFC 2119 keyword": "MUST", "children": [] }, { "id": "Requirement 5.2.5", "machine_id": "requirement_5_2_5", - "content": "If a `handler functions` terminates abnormally, other event handlers MUST run.", + "content": "If a `handler function` terminates abnormally, other `handler functions` MUST run.", "RFC 2119 keyword": "MUST", "children": [] }, diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 92a32606..1212fdb0 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -26,7 +26,7 @@ graph #### Requirement 5.1.1 -> The `provider` **MAY** define a mechanism for signaling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with an `provider event details` payload. +> The `provider` **MAY** define a mechanism for signaling the occurrence of one of a set of events, including `PROVIDER_READY`, `PROVIDER_ERROR`, `PROVIDER_CONFIGURATION_CHANGED` and `PROVIDER_STALE`, with a `provider event details` payload. If available, native event-emitter or observable/observer language constructs can be used. @@ -34,15 +34,15 @@ see: [provider event types](../types.md#provider-events), [`event details`](../t #### Requirement 5.1.2 -> When a `provider` signals the occurrence of a particular `event`, the associated `client` and `API` `event handlers` **MUST** run. +> When a `provider` signals the occurrence of a particular `event`, the associated `client` and `API` event handlers **MUST** run. see: [provider event types](./../types.md#provider-events) and [event handlers](#52-event-handlers). #### Requirement 5.1.3 -> When a `provider` signals the occurrence of a particular `event`, `event handlers` on clients which are not associated with that provider **MUST NOT** run. +> When a `provider` signals the occurrence of a particular `event`, event handlers on clients which are not associated with that provider **MUST NOT** run. -Providers bound to a named client constitute their own scope events scope. +Providers bound to a named client constitute their own "events scope". see: [setting a provider](./01-flag-evaluation.md#setting-a-provider) @@ -58,22 +58,22 @@ See [event metadata](../types.md#error-event-details) #### Requirement 5.2.1 -> The `client` **MUST** provide a function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`. +> The `client` **MUST** provide a function for associating `handler functions` with a particular `provider event type`. ```java // run the myClientOnReadyHandler function when the PROVIDER_READY event is fired - client.addHandler(ProviderEvents.Ready, MyClass::myClientOnReadyHandler); + client.addHandler(ProviderEvents.Ready, myClientOnReadyHandler); ``` -see: [provider events](#51-provider-events) +see: [provider events](#51-provider-events), [`provider event types`](../types.md#provider-events) #### Requirement 5.2.2 -> The `API` **MUST** provide a function for associating callbacks with `provider events`, which accepts an `event type` and a `event handler function`. +> The `API` **MUST** provide a function for associating `handler functions` with a particular `provider event type`. ```java // run the myGlobalErrorHandler function when the PROVIDER_READY event is fired - OpenFeature.addHandler(ProviderEvents.Error, MyClass::myGlobalErrorHandler); + OpenFeature.addHandler(ProviderEvents.Error, myGlobalErrorHandler); ``` see: [provider events](#51-provider-events), [`provider event types`](../types.md#provider-events) @@ -82,24 +82,25 @@ see: [provider events](#51-provider-events), [`provider event types`](../types.m > The `event details` **MUST** contain the `client name` associated with the event. -The `client name` indicates the client/provider with which the event is associated. -This is particularly relevant for `event handler functions` which are attached to the `API`, not a particular client. +The `client name` indicates the client/provider pair with which the event is associated. +This is especially relevant for event handlers which are attached to the `API`, not a particular client. #### Requirement 5.2.4 -> The `event handler` function **MUST** accept a `event details` parameter. +> The `handler function` **MUST** accept a `event details` parameter. see: [`event details`](../types.md#event-details) #### Requirement 5.2.5 -> If a `handler functions` terminates abnormally, other event handlers **MUST** run. +> If a `handler function` terminates abnormally, other `handler functions` **MUST** run. #### Requirement 5.2.6 > Event handlers **MUST** persist across `provider` changes. -Behavior of event handlers should be independent of the order of handler addition and provider configuration. +If a provider is changed, existing event handlers will still fire. +This means that the order of provider configuration and event handler addition is independent. #### Requirement 5.2.7 @@ -108,7 +109,7 @@ Behavior of event handlers should be independent of the order of handler additio ### Event handlers and initialization Though providers themselves need not implement events, the `flag evaluation API` uses events to convey relevant state changes during configuration and initialization. -_Application authors_ and _application integrators_ use these events to wait for proper initialization of the SDK and provider and to do basic monitoring and error handling. +_Application authors_ and _application integrators_ use these events to wait for proper initialization of the provider and to do basic monitoring and error handling. #### Requirement 5.3.1 diff --git a/specification/types.md b/specification/types.md index 5f74880a..9175e275 100644 --- a/specification/types.md +++ b/specification/types.md @@ -136,3 +136,8 @@ An enumeration of provider events. | PROVIDER_ERROR | The provider signalled an error. | | PROVIDER_CONFIGURATION_CHANGED | A change was made to the backend flag configuration. | | PROVIDER_STALE | The provider's cached state is not longer valid and may not be up-to-date with the source of truth. | + +### Handler Functions + +A function or method which can be associated with a `provider event`, and runs when that event occurs. +It declares an `event details` parameter. \ No newline at end of file From bc0452cfab8460a7d8e8492538f93381ddf7b340 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Fri, 12 May 2023 13:37:16 -0400 Subject: [PATCH 22/24] fixup: lint fix Signed-off-by: Todd Baert --- specification/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/types.md b/specification/types.md index 9175e275..c4482dca 100644 --- a/specification/types.md +++ b/specification/types.md @@ -140,4 +140,4 @@ An enumeration of provider events. ### Handler Functions A function or method which can be associated with a `provider event`, and runs when that event occurs. -It declares an `event details` parameter. \ No newline at end of file +It declares an `event details` parameter. From 5f4c75b16027d9c81bd26d8f149c8d8fe8f09215 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Fri, 12 May 2023 13:37:45 -0400 Subject: [PATCH 23/24] fixup: add event handler removal ex Signed-off-by: Todd Baert --- specification/sections/05-events.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index 1212fdb0..e700de0f 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -106,6 +106,11 @@ This means that the order of provider configuration and event handler addition i > The `API` and `client` **MUST** provide a function allowing the removal of event handlers. +```java + // remove an existing handler for a PROVIDER_CONFIGURATION_CHANGED event + client.removeHandler(ProviderEvents.ConfigurationChanged, myClientOnChangedHandler); +``` + ### Event handlers and initialization Though providers themselves need not implement events, the `flag evaluation API` uses events to convey relevant state changes during configuration and initialization. From 736f9ec509c2b512c3e06551a588fe74a1a0ba14 Mon Sep 17 00:00:00 2001 From: Todd Baert Date: Mon, 15 May 2023 08:46:38 -0400 Subject: [PATCH 24/24] Update specification/sections/05-events.md Signed-off-by: Todd Baert --- specification/sections/05-events.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/sections/05-events.md b/specification/sections/05-events.md index e700de0f..5ecf47cc 100644 --- a/specification/sections/05-events.md +++ b/specification/sections/05-events.md @@ -1,5 +1,5 @@ --- -title: Events +title: Events Extensions description: Specification defining event semantics toc_max_heading_level: 4 ---