Skip to content

David-Desmaisons/ComposableAsync

Repository files navigation

Composable Async

build NuGet Badge MIT License

Create, compose and inject asynchronous behaviors in .Net Framework and .Net Core.

Goal

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

Go nuget packages