Skip to content

Commit 4c0592e

Browse files
toddbaertaskpt
andauthored
feat!: domain instead of client name (#294)
Uses "domain" terminology instead of "client name / named client". Fixes: #249 I believe with this, we are able to release a 2.0 --------- Signed-off-by: Todd Baert <[email protected]> Co-authored-by: André Silva <[email protected]>
1 parent 00e99d6 commit 4c0592e

8 files changed

+89
-85
lines changed

README.md

+20-18
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,16 @@ public async Task Example()
6969

7070
## 🌟 Features
7171

72-
| Status | Features | Description |
73-
| ------ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
74-
|| [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
75-
|| [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
76-
|| [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
77-
|| [Logging](#logging) | Integrate with popular logging packages. |
78-
|| [Named clients](#named-clients) | Utilize multiple providers in a single application. |
79-
|| [Eventing](#eventing) | React to state changes in the provider or flag management system. |
80-
|| [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
81-
|| [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
72+
| Status | Features | Description |
73+
| ------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
74+
| | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
75+
| | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
76+
| | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
77+
| | [Logging](#logging) | Integrate with popular logging packages. |
78+
| | [Domains](#domains) | Logically bind clients with providers. |
79+
| | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
80+
| | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
81+
| | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
8282

8383
> Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌
8484
@@ -96,7 +96,7 @@ await Api.Instance.SetProviderAsync(new MyProvider());
9696
```
9797

9898
In some situations, it may be beneficial to register multiple providers in the same application.
99-
This is possible using [named clients](#named-clients), which is covered in more detail below.
99+
This is possible using [domains](#domains), which is covered in more detail below.
100100

101101
### Targeting
102102

@@ -151,27 +151,29 @@ var value = await client.GetBooleanValueAsync("boolFlag", false, context, new Fl
151151

152152
The .NET SDK uses Microsoft.Extensions.Logging. See the [manual](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging?tabs=command-line) for complete documentation.
153153

154-
### Named clients
154+
### Domains
155155

156-
Clients can be given a name.
157-
A name is a logical identifier that can be used to associate clients with a particular provider.
158-
If a name has no associated provider, the global provider is used.
156+
Clients can be assigned to a domain.
157+
A domain is a logical identifier which can be used to associate clients with a particular provider.
158+
If a domain has no associated provider, the default provider is used.
159159

160160
```csharp
161161
// registering the default provider
162162
await Api.Instance.SetProviderAsync(new LocalProvider());
163163

164-
// registering a named provider
164+
// registering a provider to a domain
165165
await Api.Instance.SetProviderAsync("clientForCache", new CachedProvider());
166166

167167
// a client backed by default provider
168168
FeatureClient clientDefault = Api.Instance.GetClient();
169169

170170
// a client backed by CachedProvider
171-
FeatureClient clientNamed = Api.Instance.GetClient("clientForCache");
172-
171+
FeatureClient scopedClient = Api.Instance.GetClient("clientForCache");
173172
```
174173

174+
Domains can be defined on a provider during registration.
175+
For more details, please refer to the [providers](#providers) section.
176+
175177
### Eventing
176178

177179
Events allow you to react to state changes in the provider or underlying flag management system, such as flag definition changes,

src/OpenFeature/Api.cs

+17-15
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,19 @@ public async Task SetProviderAsync(FeatureProvider featureProvider)
5050
}
5151

5252
/// <summary>
53-
/// Sets the feature provider to given clientName. In order to wait for the provider to be set, and
53+
/// Binds the feature provider to the given domain. In order to wait for the provider to be set, and
5454
/// initialization to complete, await the returned task.
5555
/// </summary>
56-
/// <param name="clientName">Name of client</param>
56+
/// <param name="domain">An identifier which logically binds clients with providers</param>
5757
/// <param name="featureProvider">Implementation of <see cref="FeatureProvider"/></param>
58-
public async Task SetProviderAsync(string clientName, FeatureProvider featureProvider)
58+
public async Task SetProviderAsync(string domain, FeatureProvider featureProvider)
5959
{
60-
if (string.IsNullOrWhiteSpace(clientName))
60+
if (string.IsNullOrWhiteSpace(domain))
6161
{
62-
throw new ArgumentNullException(nameof(clientName));
62+
throw new ArgumentNullException(nameof(domain));
6363
}
64-
this._eventExecutor.RegisterClientFeatureProvider(clientName, featureProvider);
65-
await this._repository.SetProviderAsync(clientName, featureProvider, this.GetContext(), this.AfterInitialization, this.AfterError).ConfigureAwait(false);
64+
this._eventExecutor.RegisterClientFeatureProvider(domain, featureProvider);
65+
await this._repository.SetProviderAsync(domain, featureProvider, this.GetContext(), this.AfterInitialization, this.AfterError).ConfigureAwait(false);
6666
}
6767

6868
/// <summary>
@@ -82,14 +82,15 @@ public FeatureProvider GetProvider()
8282
}
8383

8484
/// <summary>
85-
/// Gets the feature provider with given clientName
85+
/// Gets the feature provider with given domain
8686
/// </summary>
87-
/// <param name="clientName">Name of client</param>
88-
/// <returns>A provider associated with the given clientName, if clientName is empty or doesn't
87+
/// <param name="domain">An identifier which logically binds clients with providers</param>
88+
89+
/// <returns>A provider associated with the given domain, if domain is empty or doesn't
8990
/// have a corresponding provider the default provider will be returned</returns>
90-
public FeatureProvider GetProvider(string clientName)
91+
public FeatureProvider GetProvider(string domain)
9192
{
92-
return this._repository.GetProvider(clientName);
93+
return this._repository.GetProvider(domain);
9394
}
9495

9596
/// <summary>
@@ -104,12 +105,13 @@ public FeatureProvider GetProvider(string clientName)
104105
public Metadata? GetProviderMetadata() => this.GetProvider().GetMetadata();
105106

106107
/// <summary>
107-
/// Gets providers metadata assigned to the given clientName. If the clientName has no provider
108+
/// Gets providers metadata assigned to the given domain. If the domain has no provider
108109
/// assigned to it the default provider will be returned
109110
/// </summary>
110-
/// <param name="clientName">Name of client</param>
111+
/// <param name="domain">An identifier which logically binds clients with providers</param>
112+
111113
/// <returns>Metadata assigned to provider</returns>
112-
public Metadata? GetProviderMetadata(string clientName) => this.GetProvider(clientName).GetMetadata();
114+
public Metadata? GetProviderMetadata(string domain) => this.GetProvider(domain).GetMetadata();
113115

114116
/// <summary>
115117
/// Create a new instance of <see cref="FeatureClient"/> using the current provider

src/OpenFeature/ProviderRepository.cs

+11-11
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ private static async Task InitProviderAsync(
127127
/// <summary>
128128
/// Set a named provider
129129
/// </summary>
130-
/// <param name="clientName">the name to associate with the provider</param>
130+
/// <param name="domain">an identifier which logically binds clients with providers</param>
131131
/// <param name="featureProvider">the provider to set as the default, passing null has no effect</param>
132132
/// <param name="context">the context to initialize the provider with</param>
133133
/// <param name="afterInitSuccess">
@@ -138,15 +138,15 @@ private static async Task InitProviderAsync(
138138
/// initialization
139139
/// </param>
140140
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to cancel any async side effects.</param>
141-
public async Task SetProviderAsync(string? clientName,
141+
public async Task SetProviderAsync(string? domain,
142142
FeatureProvider? featureProvider,
143143
EvaluationContext context,
144144
Func<FeatureProvider, Task>? afterInitSuccess = null,
145145
Func<FeatureProvider, Exception, Task>? afterInitError = null,
146146
CancellationToken cancellationToken = default)
147147
{
148-
// Cannot set a provider for a null clientName.
149-
if (clientName == null)
148+
// Cannot set a provider for a null domain.
149+
if (domain == null)
150150
{
151151
return;
152152
}
@@ -155,17 +155,17 @@ public async Task SetProviderAsync(string? clientName,
155155

156156
try
157157
{
158-
this._featureProviders.TryGetValue(clientName, out var oldProvider);
158+
this._featureProviders.TryGetValue(domain, out var oldProvider);
159159
if (featureProvider != null)
160160
{
161-
this._featureProviders.AddOrUpdate(clientName, featureProvider,
161+
this._featureProviders.AddOrUpdate(domain, featureProvider,
162162
(key, current) => featureProvider);
163163
}
164164
else
165165
{
166166
// If names of clients are programmatic, then setting the provider to null could result
167167
// in unbounded growth of the collection.
168-
this._featureProviders.TryRemove(clientName, out _);
168+
this._featureProviders.TryRemove(domain, out _);
169169
}
170170

171171
// We want to allow shutdown to happen concurrently with initialization, and the caller to not
@@ -238,22 +238,22 @@ public FeatureProvider GetProvider()
238238
}
239239
}
240240

241-
public FeatureProvider GetProvider(string? clientName)
241+
public FeatureProvider GetProvider(string? domain)
242242
{
243243
#if NET6_0_OR_GREATER
244-
if (string.IsNullOrEmpty(clientName))
244+
if (string.IsNullOrEmpty(domain))
245245
{
246246
return this.GetProvider();
247247
}
248248
#else
249249
// This is a workaround for the issue in .NET Framework where string.IsNullOrEmpty is not nullable compatible.
250-
if (clientName == null || string.IsNullOrEmpty(clientName))
250+
if (domain == null || string.IsNullOrEmpty(domain))
251251
{
252252
return this.GetProvider();
253253
}
254254
#endif
255255

256-
return this._featureProviders.TryGetValue(clientName, out var featureProvider)
256+
return this._featureProviders.TryGetValue(domain, out var featureProvider)
257257
? featureProvider
258258
: this.GetProvider();
259259
}

test/OpenFeature.Benchmarks/OpenFeatureClientBenchmarks.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace OpenFeature.Benchmark
1616
[SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task")]
1717
public class OpenFeatureClientBenchmarks
1818
{
19-
private readonly string _clientName;
19+
private readonly string _domain;
2020
private readonly string _clientVersion;
2121
private readonly string _flagName;
2222
private readonly bool _defaultBoolValue;
@@ -30,7 +30,7 @@ public class OpenFeatureClientBenchmarks
3030
public OpenFeatureClientBenchmarks()
3131
{
3232
var fixture = new Fixture();
33-
this._clientName = fixture.Create<string>();
33+
this._domain = fixture.Create<string>();
3434
this._clientVersion = fixture.Create<string>();
3535
this._flagName = fixture.Create<string>();
3636
this._defaultBoolValue = fixture.Create<bool>();
@@ -40,7 +40,7 @@ public OpenFeatureClientBenchmarks()
4040
this._defaultStructureValue = fixture.Create<Value>();
4141
this._emptyFlagOptions = new FlagEvaluationOptions(ImmutableList<Hook>.Empty, ImmutableDictionary<string, object>.Empty);
4242

43-
this._client = Api.Instance.GetClient(this._clientName, this._clientVersion);
43+
this._client = Api.Instance.GetClient(this._domain, this._clientVersion);
4444
}
4545

4646
[Benchmark]

0 commit comments

Comments
 (0)