@@ -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