Skip to content

Commit 18cde17

Browse files
chore: update multi-provider spec docs (#305)
Signed-off-by: Jonathan Norris <[email protected]>
1 parent 27e4461 commit 18cde17

File tree

1 file changed

+52
-45
lines changed

1 file changed

+52
-45
lines changed

specification/appendix-a-included-utilities.md

Lines changed: 52 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ const multiProvider = new MultiProvider(
7676
],
7777
new FirstMatchStrategy()
7878
)
79+
80+
await OpenFeature.setProviderAndWait(multiProvider)
7981
```
8082

8183
From the perspective of the SDK client, this provider will now act as a “normal” spec-compliant provider, while handling the complexities of aggregating multiple providers internally.
@@ -106,6 +108,8 @@ const multiProvider = new MultiProvider([
106108
name: "ProviderB"
107109
}
108110
])
111+
112+
await OpenFeature.setProviderAndWait(multiProvider)
109113
```
110114

111115
Names for each provider are then determined like this:
@@ -130,9 +134,9 @@ Provider states can be transitioned in the ways represented here:
130134

131135
The SDK client tracks statuses of a provider as follows:
132136

133-
- Initially the status is NOT_READY
137+
- Initially the status is `NOT_READY`
134138
- Initialize function is called (if exists) and result is awaited
135-
- Successful initialize transitions state to READY, error result transitions to either ERROR or FATAL
139+
- Successful initialize transitions state to `READY`, error result transitions to either `ERROR` or `FATAL`
136140
- From this point onwards, status is only changed as a result of provider emitting events to indicate status-changing things have occurred.
137141
- It can emit events like `FATAL`, `ERROR`, `STALE` and `READY` to transition to those states.
138142

@@ -144,9 +148,7 @@ Other statuses are currently “informational”. Nevertheless, the Multi-Provid
144148
##### Multi-Provider Status
145149

146150
The Multi-Provider mimics the event handling logic that tracks statuses in the SDK, and keeps track of the status of each provider it is managing.
147-
148151
The individual status-changing events from these providers will be “captured” in the Multi-Provider, and not re-emitted to the outer SDK UNLESS they cause the status of the Multi-Provider to change.
149-
150152
The status of the Multi-Provider will change when one of its providers changes to a status that is considered higher “precedence” than the current status.
151153

152154
The precedence order is defined as:
@@ -157,8 +159,9 @@ The precedence order is defined as:
157159
- STALE
158160
- READY
159161

160-
For example, if all providers are currently in “READY” status, the Multi-Provider will be in “READY” status.
161-
If one of the providers is “STALE”, the status of the Multi-Provider will be “STALE”. If a different provider now becomes “ERROR”, the status will be “ERROR” even if the other provider is still in “STALE”.
162+
For example, if all providers are currently in `READY` status, the Multi-Provider will be in `READY` status.
163+
If one of the providers is `STALE`, the status of the Multi-Provider will be `STALE`.
164+
If a different provider now becomes `ERROR`, the status will be `ERROR` even if the other provider is still in `STALE`.
162165

163166
When the Multi-Provider changes status, it does so by emitting the appropriate event to the SDK.
164167
The “details” of that event will be **identical** to the details of the original event from one of the inner providers which triggered this state change.
@@ -171,7 +174,7 @@ This event should be re-emitted any time it occurs from any provider.
171174
The evaluation result is based on the results from evaluating each provider.
172175
There are multiple “strategies” configurable in the Multi-Provider to decide how to use the results.
173176

174-
##### Interpreting Errors
177+
#### Interpreting Errors
175178

176179
Currently, providers have multiple ways of signalling evaluation errors to the SDK.
177180
Particularly in the case of Javascript, a provider can return an evaluation result that contains an error code and message, but still has a “value” for the result. It can also throw an error.
@@ -180,7 +183,7 @@ Several providers currently use the former approach for indicating errors in ope
180183

181184
For the purposes of aggregating providers, the Multi-Provider treats both thrown and returned errors as an “error” result. If the returned error result has a value, that value will be ignored by all strategies. Only “nominal” evaluation results will be considered by the evaluation.
182185

183-
##### Strategies
186+
### Strategies
184187

185188
The Multi-Provider supports multiple ways of deciding how to evaluate the set of providers it is managing, and how to deal with any errors that are thrown.
186189

@@ -205,11 +208,11 @@ new MultiProvider(
205208
)
206209
```
207210

208-
By default, the Multi-Provider uses the FirstMatchStrategy.
211+
By default, the Multi-Provider uses the `FirstMatchStrategy`.
209212

210213
Here are some standard strategies that come with the Multi-Provider:
211214

212-
###### First Match
215+
#### First Match Strategy
213216

214217
Return the first result returned by a provider.
215218
Skip providers that indicate they had no value due to `FLAG_NOT_FOUND`.
@@ -218,19 +221,25 @@ If any provider returns an error result other than `FLAG_NOT_FOUND`, the whole e
218221

219222
As soon as a value is returned by a provider, the rest of the operation should short-circuit and not call the rest of the providers.
220223

221-
###### First Successful
224+
[See the refrence implementation](https://github.com/open-feature/js-sdk-contrib/blob/main/libs/providers/multi-provider/src/lib/strategies/FirstMatchStrategy.ts)
225+
226+
#### First Successful Strategy
222227

223228
Similar to “First Match”, except that errors from evaluated providers do not halt execution.
224229
Instead, it will return the first successful result from a provider. If no provider successfully responds, it will throw an error result.
225230

226-
###### Comparison
231+
[See the refrence implementation](https://github.com/open-feature/js-sdk-contrib/blob/main/libs/providers/multi-provider/src/lib/strategies/FirstSuccessfulStrategy.ts)
232+
233+
#### Comparison Strategy
227234

228235
Require that all providers agree on a value.
229236
If every provider returns a non-error result, and the values do not agree, the Multi-Provider should return the result from a configurable “fallback” provider.
230237
It will also call an optional “onMismatch” callback that can be used to monitor cases where mismatches of evaluation occurred.
231238
Otherwise the value of the result will be the result of the first provider in precedence order.
232239

233-
###### User Defined
240+
[See the refrence implementation](https://github.com/open-feature/js-sdk-contrib/blob/main/libs/providers/multi-provider/src/lib/strategies/ComparisonStrategy.ts)
241+
242+
#### User Defined Custom Strategy
234243

235244
Rather than making assumptions about when to use a provider’s result and when not to (which may not hold across all providers) there is also a way for the user to define their own strategy that determines whether or not to use a result or fall through to the next one.
236245

@@ -286,44 +295,42 @@ abstract class BaseEvaluationStrategy {
286295
}
287296
```
288297

289-
The `runMode` property defines whether the providers will all be evaluated at once in parallel, or whether they will be evaluated one at a time with each result determining whether to evaluate the next one in order.
290-
291-
The `shouldEvaluateThisProvider` function is called for each provider right before the Multi-Provider would evaluate it.
292-
If the function returns false, the provider will be skipped.
293-
This can be useful in cases where it’s desired to skip a provider based on what flag key is being used, or based on some state from the provider itself that indicates it shouldn’t be evaluated right now.
298+
- **`runMode`**: property defines whether the providers will all be evaluated at once in `parallel`, or whether they will be evaluated `sequentially` with each result determining whether to evaluate the next one in order.
294299

295-
The `shouldEvaluateNextProvider` function is called right after a provider is evaluated.
296-
It is called with the details of resolution or any error that was thrown (which will be caught).
297-
If the function returns true, the next provider will be called.
298-
Otherwise all remaining providers will be skipped and the results of the ones that have been evaluated so far will be passed to `determineFinalResult` .
299-
If this function throws an error, the Multi-Provider will throw an error and not evaluate further providers.
300-
This function is not called when `runMode` is `parallel`, since all providers will be executed (as long as they individually pass the `shouldEvaluateThisProvider` check)
300+
- **`shouldEvaluateThisProvider`**: function is called for each provider right before the Multi-Provider would evaluate it.
301+
- If the function returns false, the provider will be skipped.
302+
- This can be useful in cases where it’s desired to skip a provider based on what flag key is being used, or based on some state from the provider itself that indicates it shouldn’t be evaluated right now.
301303

302-
The `determineFinalResult` function is called after the resolution stage if no further providers will be called.
303-
This function can be used to decide from the set of resolutions which one should ultimately be used.
304-
The function must return a `FinalResult` object which contains the final “ResolutionDetails” and the provider that they correspond to, or an array of “errors” in the case of a non-successful result, with the provider that created each error.
304+
- **`shouldEvaluateNextProvider`**: function is called right after a provider is evaluated.
305+
- It is called with the details of resolution or any error that was thrown (which will be caught).
306+
- If the function returns true, the next provider will be called.
307+
- Otherwise all remaining providers will be skipped and the results of the ones that have been evaluated so far will be passed to `determineFinalResult` .
308+
- If this function throws an error, the Multi-Provider will throw an error and not evaluate further providers.
309+
- This function is not called when `runMode` is `parallel`, since all providers will be executed (as long as they individually pass the `shouldEvaluateThisProvider` check)
305310

306-
To see reference implementations of the above-mentioned strategies, check out the source
311+
- **`determineFinalResult`**: function is called after the resolution stage if no further providers will be called.
312+
- This function can be used to decide from the set of resolutions which one should ultimately be used.
313+
- The function must return a `FinalResult` object which contains the final `ResolutionDetails` and the provider that they correspond to, or an array of `errors` in the case of a non-successful result, with the provider that created each error.
307314

308-
[https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/multi-provider/src/lib/strategies](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/multi-provider/src/lib/strategies)
315+
To see [reference implementations](https://github.com/open-feature/js-sdk-contrib/tree/main/libs/providers/multi-provider/src/lib/strategies) of the above-mentioned strategies.
309316

310-
#### Hooks
317+
### Hooks
311318

312319
Provider hooks are capable of modifying the context before an evaluation takes place.
313320
This behavior must be preserved, but it’s also necessary to prevent these hooks from interfering with the context being passed to other providers.
314321

315322
For this reason, the Multi-Provider manages calling the hooks of each provider itself, at the appropriate time.
316-
It then uses the result of the before hooks for a given provider as the new evaluation context when evaluating *that provider*, without affecting the context used for other providers.
323+
It then uses the result of the before hooks for a given provider as the new evaluation context when evaluating **that provider**, without affecting the context used for other providers.
317324

318325
It then calls the after, error and finally hooks using the appropriate context as well.
319326

320327
Errors thrown from these hooks are be bubbled up to the client, depending on how the evaluation “strategy” defines what to do with errors.
321328

322-
#### Shutdown
329+
### Shutdown
323330

324-
The shutdown method should ensure that shutdown is called in all underlying providers, and bubble up any errors to the client
331+
The shutdown method should ensure that `shutdown()` is called in all underlying providers, and bubble up any errors to the client
325332

326-
#### Error Handling
333+
### Error Handling
327334

328335
In cases where all providers are being called (Evaluation etc.) there may be more than one error encountered from more than one provider.
329336
The Multi-Provider will collect and throw all errors in an aggregated form as follows:
@@ -334,12 +341,12 @@ error = {
334341
code: SOME_ERROR,
335342
// which provider caused the error
336343
originalErrors: [
337-
{
338-
source: 'ProviderA',
339-
error: {
340-
message: 'something',
341-
}
342-
}
344+
{
345+
source: 'ProviderA',
346+
error: {
347+
message: 'something',
348+
}
349+
}
343350
]
344351
}
345352
```
@@ -348,17 +355,17 @@ In the case where only one error is thrown by one provider, it will still throw
348355

349356
Other errors from the Multi-Provider itself will use standard error types.
350357

351-
#### Metadata
358+
### Metadata
352359

353360
Providers can contain metadata. The Multi-Provider will make that metadata available within its own metadata as follows:
354361

355362
```javascript
356363
{
357364
name: 'multiprovider',
358-
originalMetadata: {
359-
providerA: {...},
360-
providerB: {...}
361-
},
365+
originalMetadata: {
366+
providerA: {...},
367+
providerB: {...}
368+
},
362369
}
363370
```
364371

0 commit comments

Comments
 (0)