Skip to content

Commit 2919c2f

Browse files
toddbaertaskptaustindrenski
authored
chore: revert breaking setProvider (#190)
Signed-off-by: Todd Baert <[email protected]> Co-authored-by: André Silva <[email protected]> Co-authored-by: Austin Drenski <[email protected]>
1 parent 26cd5cd commit 2919c2f

8 files changed

+123
-73
lines changed

src/OpenFeature/Api.cs

+27-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Linq;
@@ -36,25 +37,48 @@ static Api() { }
3637
private Api() { }
3738

3839
/// <summary>
39-
/// Sets the feature provider. In order to wait for the provider to be set, and initialization to complete,
40+
/// Sets the default feature provider to given clientName without awaiting its initialization.
41+
/// </summary>
42+
/// <remarks>The provider cannot be set to null. Attempting to set the provider to null has no effect.</remarks>
43+
/// <param name="featureProvider">Implementation of <see cref="FeatureProvider"/></param>
44+
[Obsolete("Will be removed in later versions; use SetProviderAsync, which can be awaited")]
45+
public void SetProvider(FeatureProvider featureProvider)
46+
{
47+
this._eventExecutor.RegisterDefaultFeatureProvider(featureProvider);
48+
_ = this._repository.SetProvider(featureProvider, this.GetContext());
49+
}
50+
51+
/// <summary>
52+
/// Sets the default feature provider. In order to wait for the provider to be set, and initialization to complete,
4053
/// await the returned task.
4154
/// </summary>
4255
/// <remarks>The provider cannot be set to null. Attempting to set the provider to null has no effect.</remarks>
4356
/// <param name="featureProvider">Implementation of <see cref="FeatureProvider"/></param>
44-
public async Task SetProvider(FeatureProvider featureProvider)
57+
public async Task SetProviderAsync(FeatureProvider featureProvider)
4558
{
4659
this._eventExecutor.RegisterDefaultFeatureProvider(featureProvider);
4760
await this._repository.SetProvider(featureProvider, this.GetContext()).ConfigureAwait(false);
4861
}
4962

63+
/// <summary>
64+
/// Sets the feature provider to given clientName without awaiting its initialization.
65+
/// </summary>
66+
/// <param name="clientName">Name of client</param>
67+
/// <param name="featureProvider">Implementation of <see cref="FeatureProvider"/></param>
68+
[Obsolete("Will be removed in later versions; use SetProviderAsync, which can be awaited")]
69+
public void SetProvider(string clientName, FeatureProvider featureProvider)
70+
{
71+
this._eventExecutor.RegisterClientFeatureProvider(clientName, featureProvider);
72+
_ = this._repository.SetProvider(clientName, featureProvider, this.GetContext());
73+
}
5074

5175
/// <summary>
5276
/// Sets the feature provider to given clientName. In order to wait for the provider to be set, and
5377
/// initialization to complete, await the returned task.
5478
/// </summary>
5579
/// <param name="clientName">Name of client</param>
5680
/// <param name="featureProvider">Implementation of <see cref="FeatureProvider"/></param>
57-
public async Task SetProvider(string clientName, FeatureProvider featureProvider)
81+
public async Task SetProviderAsync(string clientName, FeatureProvider featureProvider)
5882
{
5983
this._eventExecutor.RegisterClientFeatureProvider(clientName, featureProvider);
6084
await this._repository.SetProvider(clientName, featureProvider, this.GetContext()).ConfigureAwait(false);

test/OpenFeature.E2ETests/Steps/EvaluationStepDefinitions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public EvaluationStepDefinitions(ScenarioContext scenarioContext)
4242
{
4343
_scenarioContext = scenarioContext;
4444
var flagdProvider = new FlagdProvider();
45-
Api.Instance.SetProvider(flagdProvider).Wait();
45+
Api.Instance.SetProviderAsync(flagdProvider).Wait();
4646
client = Api.Instance.GetClient();
4747
}
4848

test/OpenFeature.Tests/ClearOpenFeatureInstanceFixture.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public ClearOpenFeatureInstanceFixture()
77
{
88
Api.Instance.SetContext(null);
99
Api.Instance.ClearHooks();
10-
Api.Instance.SetProvider(new NoOpFeatureProvider()).Wait();
10+
Api.Instance.SetProviderAsync(new NoOpFeatureProvider()).Wait();
1111
}
1212
}
1313
}

test/OpenFeature.Tests/OpenFeatureClientTests.cs

+11-11
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public async Task OpenFeatureClient_Should_Allow_Flag_Evaluation()
7575
var defaultStructureValue = fixture.Create<Value>();
7676
var emptyFlagOptions = new FlagEvaluationOptions(ImmutableList<Hook>.Empty, ImmutableDictionary<string, object>.Empty);
7777

78-
await Api.Instance.SetProvider(new NoOpFeatureProvider());
78+
await Api.Instance.SetProviderAsync(new NoOpFeatureProvider());
7979
var client = Api.Instance.GetClient(clientName, clientVersion);
8080

8181
(await client.GetBooleanValue(flagName, defaultBoolValue)).Should().Be(defaultBoolValue);
@@ -121,7 +121,7 @@ public async Task OpenFeatureClient_Should_Allow_Details_Flag_Evaluation()
121121
var defaultStructureValue = fixture.Create<Value>();
122122
var emptyFlagOptions = new FlagEvaluationOptions(ImmutableList<Hook>.Empty, ImmutableDictionary<string, object>.Empty);
123123

124-
await Api.Instance.SetProvider(new NoOpFeatureProvider());
124+
await Api.Instance.SetProviderAsync(new NoOpFeatureProvider());
125125
var client = Api.Instance.GetClient(clientName, clientVersion);
126126

127127
var boolFlagEvaluationDetails = new FlagEvaluationDetails<bool>(flagName, defaultBoolValue, ErrorType.None, NoOpProvider.ReasonNoOp, NoOpProvider.Variant);
@@ -172,7 +172,7 @@ public async Task OpenFeatureClient_Should_Return_DefaultValue_When_Type_Mismatc
172172
mockedFeatureProvider.GetMetadata().Returns(new Metadata(fixture.Create<string>()));
173173
mockedFeatureProvider.GetProviderHooks().Returns(ImmutableList<Hook>.Empty);
174174

175-
await Api.Instance.SetProvider(mockedFeatureProvider);
175+
await Api.Instance.SetProviderAsync(mockedFeatureProvider);
176176
var client = Api.Instance.GetClient(clientName, clientVersion, mockedLogger);
177177

178178
var evaluationDetails = await client.GetObjectDetails(flagName, defaultValue);
@@ -202,7 +202,7 @@ public async Task Should_Resolve_BooleanValue()
202202
featureProviderMock.GetMetadata().Returns(new Metadata(fixture.Create<string>()));
203203
featureProviderMock.GetProviderHooks().Returns(ImmutableList<Hook>.Empty);
204204

205-
await Api.Instance.SetProvider(featureProviderMock);
205+
await Api.Instance.SetProviderAsync(featureProviderMock);
206206
var client = Api.Instance.GetClient(clientName, clientVersion);
207207

208208
(await client.GetBooleanValue(flagName, defaultValue)).Should().Be(defaultValue);
@@ -224,7 +224,7 @@ public async Task Should_Resolve_StringValue()
224224
featureProviderMock.GetMetadata().Returns(new Metadata(fixture.Create<string>()));
225225
featureProviderMock.GetProviderHooks().Returns(ImmutableList<Hook>.Empty);
226226

227-
await Api.Instance.SetProvider(featureProviderMock);
227+
await Api.Instance.SetProviderAsync(featureProviderMock);
228228
var client = Api.Instance.GetClient(clientName, clientVersion);
229229

230230
(await client.GetStringValue(flagName, defaultValue)).Should().Be(defaultValue);
@@ -246,7 +246,7 @@ public async Task Should_Resolve_IntegerValue()
246246
featureProviderMock.GetMetadata().Returns(new Metadata(fixture.Create<string>()));
247247
featureProviderMock.GetProviderHooks().Returns(ImmutableList<Hook>.Empty);
248248

249-
await Api.Instance.SetProvider(featureProviderMock);
249+
await Api.Instance.SetProviderAsync(featureProviderMock);
250250
var client = Api.Instance.GetClient(clientName, clientVersion);
251251

252252
(await client.GetIntegerValue(flagName, defaultValue)).Should().Be(defaultValue);
@@ -268,7 +268,7 @@ public async Task Should_Resolve_DoubleValue()
268268
featureProviderMock.GetMetadata().Returns(new Metadata(fixture.Create<string>()));
269269
featureProviderMock.GetProviderHooks().Returns(ImmutableList<Hook>.Empty);
270270

271-
await Api.Instance.SetProvider(featureProviderMock);
271+
await Api.Instance.SetProviderAsync(featureProviderMock);
272272
var client = Api.Instance.GetClient(clientName, clientVersion);
273273

274274
(await client.GetDoubleValue(flagName, defaultValue)).Should().Be(defaultValue);
@@ -290,7 +290,7 @@ public async Task Should_Resolve_StructureValue()
290290
featureProviderMock.GetMetadata().Returns(new Metadata(fixture.Create<string>()));
291291
featureProviderMock.GetProviderHooks().Returns(ImmutableList<Hook>.Empty);
292292

293-
await Api.Instance.SetProvider(featureProviderMock);
293+
await Api.Instance.SetProviderAsync(featureProviderMock);
294294
var client = Api.Instance.GetClient(clientName, clientVersion);
295295

296296
(await client.GetObjectValue(flagName, defaultValue)).Should().Be(defaultValue);
@@ -313,7 +313,7 @@ public async Task When_Error_Is_Returned_From_Provider_Should_Return_Error()
313313
featureProviderMock.GetMetadata().Returns(new Metadata(fixture.Create<string>()));
314314
featureProviderMock.GetProviderHooks().Returns(ImmutableList<Hook>.Empty);
315315

316-
await Api.Instance.SetProvider(featureProviderMock);
316+
await Api.Instance.SetProviderAsync(featureProviderMock);
317317
var client = Api.Instance.GetClient(clientName, clientVersion);
318318
var response = await client.GetObjectDetails(flagName, defaultValue);
319319

@@ -338,7 +338,7 @@ public async Task When_Exception_Occurs_During_Evaluation_Should_Return_Error()
338338
featureProviderMock.GetMetadata().Returns(new Metadata(fixture.Create<string>()));
339339
featureProviderMock.GetProviderHooks().Returns(ImmutableList<Hook>.Empty);
340340

341-
await Api.Instance.SetProvider(featureProviderMock);
341+
await Api.Instance.SetProviderAsync(featureProviderMock);
342342
var client = Api.Instance.GetClient(clientName, clientVersion);
343343
var response = await client.GetObjectDetails(flagName, defaultValue);
344344

@@ -351,7 +351,7 @@ public async Task When_Exception_Occurs_During_Evaluation_Should_Return_Error()
351351
[Fact]
352352
public async Task Should_Use_No_Op_When_Provider_Is_Null()
353353
{
354-
await Api.Instance.SetProvider(null);
354+
await Api.Instance.SetProviderAsync(null);
355355
var client = new FeatureClient("test", "test");
356356
(await client.GetIntegerValue("some-key", 12)).Should().Be(12);
357357
}

test/OpenFeature.Tests/OpenFeatureEventTests.cs

+43-17
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public async Task API_Level_Event_Handlers_Should_Be_Registered()
7070
Api.Instance.AddHandler(ProviderEventTypes.ProviderStale, eventHandler);
7171

7272
var testProvider = new TestProvider();
73-
await Api.Instance.SetProvider(testProvider);
73+
await Api.Instance.SetProviderAsync(testProvider);
7474

7575
testProvider.SendEvent(ProviderEventTypes.ProviderConfigurationChanged);
7676
testProvider.SendEvent(ProviderEventTypes.ProviderError);
@@ -117,7 +117,33 @@ public async Task API_Level_Event_Handlers_Should_Be_Informed_About_Ready_State_
117117
var eventHandler = Substitute.For<EventHandlerDelegate>();
118118

119119
var testProvider = new TestProvider();
120-
await Api.Instance.SetProvider(testProvider);
120+
await Api.Instance.SetProviderAsync(testProvider);
121+
122+
Api.Instance.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
123+
124+
await Utils.AssertUntilAsync(_ => eventHandler
125+
.Received()
126+
.Invoke(
127+
Arg.Is<ProviderEventPayload>(
128+
payload => payload.ProviderName == testProvider.GetMetadata().Name && payload.Type == ProviderEventTypes.ProviderReady
129+
)));
130+
}
131+
132+
[Fact]
133+
[Specification("5.1.2", "When a `provider` signals the occurrence of a particular `event`, the associated `client` and `API` event handlers MUST run.")]
134+
[Specification("5.2.2", "The `API` MUST provide a function for associating `handler functions` with a particular `provider event type`.")]
135+
[Specification("5.2.3", "The `event details` MUST contain the `provider name` associated with the event.")]
136+
[Specification("5.2.4", "The `handler function` MUST accept a `event details` parameter.")]
137+
[Specification("5.3.1", "If the provider's `initialize` function terminates normally, `PROVIDER_READY` handlers MUST run.")]
138+
[Specification("5.3.3", "Handlers attached after the provider is already in the associated state, MUST run immediately.")]
139+
public async Task API_Level_Event_Handlers_Should_Be_Informed_About_Ready_State_After_Registering_Provider_Ready_Sync()
140+
{
141+
var eventHandler = Substitute.For<EventHandlerDelegate>();
142+
143+
var testProvider = new TestProvider();
144+
#pragma warning disable CS0618 // Type or member is obsolete
145+
Api.Instance.SetProvider(testProvider);
146+
#pragma warning restore CS0618 // Type or member is obsolete
121147

122148
Api.Instance.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
123149

@@ -141,7 +167,7 @@ public async Task API_Level_Event_Handlers_Should_Be_Informed_About_Error_State_
141167
var eventHandler = Substitute.For<EventHandlerDelegate>();
142168

143169
var testProvider = new TestProvider();
144-
await Api.Instance.SetProvider(testProvider);
170+
await Api.Instance.SetProviderAsync(testProvider);
145171

146172
testProvider.SetStatus(ProviderStatus.Error);
147173

@@ -166,7 +192,7 @@ public async Task API_Level_Event_Handlers_Should_Be_Informed_About_Stale_State_
166192
var eventHandler = Substitute.For<EventHandlerDelegate>();
167193

168194
var testProvider = new TestProvider();
169-
await Api.Instance.SetProvider(testProvider);
195+
await Api.Instance.SetProviderAsync(testProvider);
170196

171197
testProvider.SetStatus(ProviderStatus.Stale);
172198

@@ -194,12 +220,12 @@ public async Task API_Level_Event_Handlers_Should_Be_Exchangeable()
194220
Api.Instance.AddHandler(ProviderEventTypes.ProviderConfigurationChanged, eventHandler);
195221

196222
var testProvider = new TestProvider();
197-
await Api.Instance.SetProvider(testProvider);
223+
await Api.Instance.SetProviderAsync(testProvider);
198224

199225
testProvider.SendEvent(ProviderEventTypes.ProviderConfigurationChanged);
200226

201227
var newTestProvider = new TestProvider();
202-
await Api.Instance.SetProvider(newTestProvider);
228+
await Api.Instance.SetProviderAsync(newTestProvider);
203229

204230
newTestProvider.SendEvent(ProviderEventTypes.ProviderConfigurationChanged);
205231

@@ -223,13 +249,13 @@ public async Task API_Level_Event_Handlers_Should_Be_Removable()
223249
Api.Instance.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
224250

225251
var testProvider = new TestProvider();
226-
await Api.Instance.SetProvider(testProvider);
252+
await Api.Instance.SetProviderAsync(testProvider);
227253

228254
Thread.Sleep(1000);
229255
Api.Instance.RemoveHandler(ProviderEventTypes.ProviderReady, eventHandler);
230256

231257
var newTestProvider = new TestProvider();
232-
await Api.Instance.SetProvider(newTestProvider);
258+
await Api.Instance.SetProviderAsync(newTestProvider);
233259

234260
eventHandler.Received(1).Invoke(Arg.Is<ProviderEventPayload>(payload => payload.ProviderName == testProvider.GetMetadata().Name));
235261
}
@@ -254,7 +280,7 @@ public async Task API_Level_Event_Handlers_Should_Be_Executed_When_Other_Handler
254280
Api.Instance.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
255281

256282
var testProvider = new TestProvider(fixture.Create<string>());
257-
await Api.Instance.SetProvider(testProvider);
283+
await Api.Instance.SetProviderAsync(testProvider);
258284

259285
await Utils.AssertUntilAsync(
260286
_ => failingEventHandler.Received().Invoke(Arg.Is<ProviderEventPayload>(payload => payload.ProviderName == testProvider.GetMetadata().Name))
@@ -277,7 +303,7 @@ public async Task Client_Level_Event_Handlers_Should_Be_Registered()
277303
var myClient = Api.Instance.GetClient(fixture.Create<string>());
278304

279305
var testProvider = new TestProvider();
280-
await Api.Instance.SetProvider(myClient.GetMetadata().Name, testProvider);
306+
await Api.Instance.SetProviderAsync(myClient.GetMetadata().Name, testProvider);
281307

282308
myClient.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
283309

@@ -306,7 +332,7 @@ public async Task Client_Level_Event_Handlers_Should_Be_Executed_When_Other_Hand
306332
myClient.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
307333

308334
var testProvider = new TestProvider();
309-
await Api.Instance.SetProvider(myClient.GetMetadata().Name, testProvider);
335+
await Api.Instance.SetProviderAsync(myClient.GetMetadata().Name, testProvider);
310336

311337
await Utils.AssertUntilAsync(
312338
_ => failingEventHandler.Received().Invoke(Arg.Is<ProviderEventPayload>(payload => payload.ProviderName == testProvider.GetMetadata().Name))
@@ -335,9 +361,9 @@ public async Task Client_Level_Event_Handlers_Should_Be_Registered_To_Default_Pr
335361
var clientProvider = new TestProvider(fixture.Create<string>());
336362

337363
// set the default provider on API level, but not specifically to the client
338-
await Api.Instance.SetProvider(apiProvider);
364+
await Api.Instance.SetProviderAsync(apiProvider);
339365
// set the other provider specifically for the client
340-
await Api.Instance.SetProvider(myClientWithBoundProvider.GetMetadata().Name, clientProvider);
366+
await Api.Instance.SetProviderAsync(myClientWithBoundProvider.GetMetadata().Name, clientProvider);
341367

342368
myClientWithNoBoundProvider.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
343369
myClientWithBoundProvider.AddHandler(ProviderEventTypes.ProviderReady, clientEventHandler);
@@ -367,7 +393,7 @@ public async Task Client_Level_Event_Handlers_Should_Be_Receive_Events_From_Name
367393
var clientProvider = new TestProvider(fixture.Create<string>());
368394

369395
// set the default provider
370-
await Api.Instance.SetProvider(defaultProvider);
396+
await Api.Instance.SetProviderAsync(defaultProvider);
371397

372398
client.AddHandler(ProviderEventTypes.ProviderConfigurationChanged, clientEventHandler);
373399

@@ -379,7 +405,7 @@ await Utils.AssertUntilAsync(
379405
);
380406

381407
// set the other provider specifically for the client
382-
await Api.Instance.SetProvider(client.GetMetadata().Name, clientProvider);
408+
await Api.Instance.SetProviderAsync(client.GetMetadata().Name, clientProvider);
383409

384410
// now, send another event for the default handler
385411
defaultProvider.SendEvent(ProviderEventTypes.ProviderConfigurationChanged);
@@ -410,7 +436,7 @@ public async Task Client_Level_Event_Handlers_Should_Be_Informed_About_Ready_Sta
410436
var myClient = Api.Instance.GetClient(fixture.Create<string>());
411437

412438
var testProvider = new TestProvider();
413-
await Api.Instance.SetProvider(myClient.GetMetadata().Name, testProvider);
439+
await Api.Instance.SetProviderAsync(myClient.GetMetadata().Name, testProvider);
414440

415441
// add the event handler after the provider has already transitioned into the ready state
416442
myClient.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
@@ -435,7 +461,7 @@ public async Task Client_Level_Event_Handlers_Should_Be_Removable()
435461
myClient.AddHandler(ProviderEventTypes.ProviderReady, eventHandler);
436462

437463
var testProvider = new TestProvider();
438-
await Api.Instance.SetProvider(myClient.GetMetadata().Name, testProvider);
464+
await Api.Instance.SetProviderAsync(myClient.GetMetadata().Name, testProvider);
439465

440466
// wait for the first event to be received
441467
await Utils.AssertUntilAsync(_ => myClient.RemoveHandler(ProviderEventTypes.ProviderReady, eventHandler));

0 commit comments

Comments
 (0)