Skip to content

Commit 39b3e9c

Browse files
committed
Adding transaction propagator to the Api.
Signed-off-by: André Silva <2493377+askpt@users.noreply.github.com>
1 parent 0b6007b commit 39b3e9c

1 file changed

Lines changed: 62 additions & 13 deletions

File tree

src/OpenFeature/Api.cs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public sealed class Api : IEventBus
2222
private EventExecutor _eventExecutor = new EventExecutor();
2323
private ProviderRepository _repository = new ProviderRepository();
2424
private readonly ConcurrentStack<Hook> _hooks = new ConcurrentStack<Hook>();
25+
private ITransactionContextPropagator? _transactionContextPropagator;
26+
private object _transactionContextPropagatorLock = new();
2527

2628
/// The reader/writer locks are not disposed because the singleton instance should never be disposed.
2729
private readonly ReaderWriterLockSlim _evaluationContextLock = new ReaderWriterLockSlim();
@@ -46,7 +48,9 @@ private Api() { }
4648
public async Task SetProviderAsync(FeatureProvider featureProvider)
4749
{
4850
this._eventExecutor.RegisterDefaultFeatureProvider(featureProvider);
49-
await this._repository.SetProviderAsync(featureProvider, this.GetContext(), this.AfterInitialization, this.AfterError).ConfigureAwait(false);
51+
await this._repository
52+
.SetProviderAsync(featureProvider, this.GetContext(), this.AfterInitialization, this.AfterError)
53+
.ConfigureAwait(false);
5054
}
5155

5256
/// <summary>
@@ -61,8 +65,11 @@ public async Task SetProviderAsync(string domain, FeatureProvider featureProvide
6165
{
6266
throw new ArgumentNullException(nameof(domain));
6367
}
68+
6469
this._eventExecutor.RegisterClientFeatureProvider(domain, featureProvider);
65-
await this._repository.SetProviderAsync(domain, featureProvider, this.GetContext(), this.AfterInitialization, this.AfterError).ConfigureAwait(false);
70+
await this._repository
71+
.SetProviderAsync(domain, featureProvider, this.GetContext(), this.AfterInitialization, this.AfterError)
72+
.ConfigureAwait(false);
6673
}
6774

6875
/// <summary>
@@ -85,7 +92,6 @@ public FeatureProvider GetProvider()
8592
/// Gets the feature provider with given domain
8693
/// </summary>
8794
/// <param name="domain">An identifier which logically binds clients with providers</param>
88-
8995
/// <returns>A provider associated with the given domain, if domain is empty or doesn't
9096
/// have a corresponding provider the default provider will be returned</returns>
9197
public FeatureProvider GetProvider(string domain)
@@ -109,7 +115,6 @@ public FeatureProvider GetProvider(string domain)
109115
/// assigned to it the default provider will be returned
110116
/// </summary>
111117
/// <param name="domain">An identifier which logically binds clients with providers</param>
112-
113118
/// <returns>Metadata assigned to provider</returns>
114119
public Metadata? GetProviderMetadata(string domain) => this.GetProvider(domain).GetMetadata();
115120

@@ -218,22 +223,62 @@ public EvaluationContext GetContext()
218223
}
219224
}
220225

226+
/// <summary>
227+
/// Return the transaction context propagator.
228+
/// </summary>
229+
/// <returns><see cref="ITransactionContextPropagator"/>the registered transaction context propagator</returns>
230+
public ITransactionContextPropagator? GetTransactionContextPropagator()
231+
{
232+
return this._transactionContextPropagator;
233+
}
234+
235+
/// <summary>
236+
/// Sets the transaction context propagator.
237+
/// </summary>
238+
/// <param name="transactionContextPropagator">the transaction context propagator to be registered</param>
239+
/// <exception cref="ArgumentNullException">Transaction context propagator cannot be null</exception>
240+
public void SetTransactionContextPropagator(ITransactionContextPropagator transactionContextPropagator)
241+
{
242+
if (transactionContextPropagator == null)
243+
{
244+
throw new ArgumentNullException(nameof(transactionContextPropagator),
245+
"Transaction context propagator cannot be null");
246+
}
247+
248+
lock (this._transactionContextPropagatorLock)
249+
{
250+
this._transactionContextPropagator = transactionContextPropagator;
251+
}
252+
}
253+
221254
/// <summary>
222255
/// Returns the currently defined transaction context using the registered transaction context propagator.
223256
/// </summary>
224257
/// <returns><see cref="EvaluationContext"/>The current transaction context</returns>
225-
public EvaluationContext GetTransactionContext() {
226-
// return this.transactionContextPropagator.getTransactionContext();
227-
throw new NotImplementedException();
258+
public EvaluationContext? GetTransactionContext()
259+
{
260+
return this._transactionContextPropagator?.GetTransactionContext();
228261
}
229262

230263
/// <summary>
231264
/// Sets the transaction context using the registered transaction context propagator.
232265
/// </summary>
233266
/// <param name="evaluationContext">The <see cref="EvaluationContext"/> to set</param>
234-
public void SetTransactionContext(EvaluationContext evaluationContext) {
235-
// this.transactionContextPropagator.setTransactionContext(evaluationContext);
236-
throw new NotImplementedException();
267+
/// <exception cref="InvalidOperationException">Transaction context propagator is not set.</exception>
268+
/// <exception cref="ArgumentNullException">Evaluation context cannot be null</exception>
269+
public void SetTransactionContext(EvaluationContext evaluationContext)
270+
{
271+
if (evaluationContext == null)
272+
{
273+
throw new ArgumentNullException(nameof(evaluationContext), "Evaluation context cannot be null");
274+
}
275+
276+
if (this._transactionContextPropagator == null)
277+
{
278+
throw new InvalidOperationException("Transaction context propagator is not set");
279+
}
280+
281+
this._transactionContextPropagator?.SetTransactionContext(evaluationContext);
237282
}
238283

239284
/// <summary>
@@ -300,23 +345,27 @@ private async Task AfterInitialization(FeatureProvider provider)
300345
ProviderName = provider.GetMetadata()?.Name,
301346
};
302347

303-
await this._eventExecutor.EventChannel.Writer.WriteAsync(new Event { Provider = provider, EventPayload = eventPayload }).ConfigureAwait(false);
348+
await this._eventExecutor.EventChannel.Writer
349+
.WriteAsync(new Event { Provider = provider, EventPayload = eventPayload }).ConfigureAwait(false);
304350
}
305351

306352
/// <summary>
307353
/// Update the provider state to ERROR and emit an ERROR after failed init.
308354
/// </summary>
309355
private async Task AfterError(FeatureProvider provider, Exception? ex)
310356
{
311-
provider.Status = typeof(ProviderFatalException) == ex?.GetType() ? ProviderStatus.Fatal : ProviderStatus.Error;
357+
provider.Status = typeof(ProviderFatalException) == ex?.GetType()
358+
? ProviderStatus.Fatal
359+
: ProviderStatus.Error;
312360
var eventPayload = new ProviderEventPayload
313361
{
314362
Type = ProviderEventTypes.ProviderError,
315363
Message = $"Provider initialization error: {ex?.Message}",
316364
ProviderName = provider.GetMetadata()?.Name,
317365
};
318366

319-
await this._eventExecutor.EventChannel.Writer.WriteAsync(new Event { Provider = provider, EventPayload = eventPayload }).ConfigureAwait(false);
367+
await this._eventExecutor.EventChannel.Writer
368+
.WriteAsync(new Event { Provider = provider, EventPayload = eventPayload }).ConfigureAwait(false);
320369
}
321370
}
322371
}

0 commit comments

Comments
 (0)