Composable Async
Create, compose and inject asynchronous behaviors in .Net Framework and .Net Core.
Goal
Create asynchronous behavior such as fiber, rate limiter, circuit breaker.
Compose these behaviors and use them as building blocks with aspect oriented programming.
Provide a lightweight way inject these behaviors to transform POCOs in actors.
Create asynchronous behavior
Asynchronous behaviors are implemented using IDispatcher abstraction.
Composable Async provides various dispatchers implementation:
Retry
// Create dispatcher that catch all ArgumentException and retry for ever with a delay of 200 ms
var retryDispatcher = RetryPolicy.For<ArgumentException>().WithWaitBetweenRetry(TimeSpan.FromSeconds(0.2)).ForEver();
See more at ComposableAsync.Resilient
Circuit-Breaker
// Create dispatcher that catch all ArgumentException and retry for ever with a delay of 200 ms
var retryDispatcher = CircuitBreakerPolicy.For<TimeoutException>().WithRetryAndTimeout(10, TimeSpan.FromMilliseconds(500));
See more at ComposableAsync.Resilient
Fiber
// Create dispatcher that dispatch all action on the same thread
var fiberDispatcher = Fiber.CreateMonoThreadedFiber();
See more at ComposableAsync.Concurrent
RateLimiter
// Create dispatcher that dispatch all action on the same thread
var timeConstraint = TimeLimiter.GetFromMaxCountByInterval(5, TimeSpan.FromSeconds(1));
See more at RateLimiter
Compose dispatchers
Use then extension methods to create a dispatcher that will execute sequentially dispatchers
/// <summary>
/// Returns a composed dispatcher applying the given dispatchers sequentially
/// </summary>
/// <param name="dispatcher"></param>
/// <param name="others"></param>
/// <returns></returns>
public static IDispatcher Then(this IDispatcher dispatcher, IEnumerable<IDispatcher> others)
var composed = fiberDispatcher.Then(timeConstraint);
Use dispatchers
Await dispatcher
await fiberDispatcher;
// After the await, the code executes in the dispatcher context
// In this case the code will execute on the fiber thread
Console.WriteLine($"This is fiber thread {Thread.CurrentThread.ManagedThreadId}");
As httpDelegateHandler
Transform a dispatcher into HttpMessageHandler with AsDelegatingHandler extension method:
/// Using time limiter nuget
var handler = TimeLimiter
.GetFromMaxCountByInterval(60, TimeSpan.FromMinutes(1))
.AsDelegatingHandler();
var client = new HttpClient(handler);
As wrapper for proxy Factory
Using ComposableAsync.Factory
, with this option all methods call to the proxyfied object are wrapped using the provided dispatcher.
var retryDispatcher = RetryPolicy.For<SystemException>().ForEver();
var originalObject = new BusinessObject();
var proxyFactory = new ProxyFactory(retryDispatcher);
var proxyObject = proxyFactory.Build<IBusinessObject>(originalObject);
// The call to the originalObject will be wrapped into a retry policy for SystemException
var res = await proxyObject.Execute(cancellationToken);
Actors
ComposableAsync.Concurrent
also provides an actor factory based on fiber and proxy factory.
// Instantiate actor factory
var builder = new ActorFactoryBuilder();
var factory = builder.GetActorFactory(shared: false);
// When shared is true, all actor leaves in the same thread,
// when shared is false, each actor leaves in its own thread.
// Instantiate an actor from a POCO
var fooActor = fact.Build<IFoo>(new ConcreteFoo());
See more at ComposableAsync.Concurrent
Nuget
For core functionality:
Install-Package ComposableAsync.Core
For factories:
Install-Package ComposableAsync.Factory
For actors:
Install-Package ComposableAsync.Concurrent
For retry and circuit-breaker:
Install-Package ComposableAsync.Resilient