I am busy implementing a EventProcessorHost client for an azure EventBus client.
I have a class that implements IEventProcessor as follows:
public class MyEventProcessor : IEventProcessor
{
Stopwatch checkpointStopWatch;
//TODO: get provider id from parent class
public async Task CloseAsync(PartitionContext context, CloseReason reason)
{
Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason);
if (reason == CloseReason.Shutdown)
{
await context.CheckpointAsync();
}
}
public Task OpenAsync(PartitionContext context)
{
Debug.WriteLine("SimpleEventProcessor initialized. Partition: '{0}', Offset: '{1}'", context.Lease.PartitionId, context.Lease.Offset);
eventHandler = new MyEventHandler();
this.checkpointStopWatch = new Stopwatch();
this.checkpointStopWatch.Start();
return Task.FromResult<object>(null);
}
async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
foreach (EventData eventData in messages)
{
string data = Encoding.UTF8.GetString(eventData.GetBytes());
Debug.WriteLine(data);
}
//Call checkpoint every 5 minutes, so that worker can resume processing from the 5 minutes back if it restarts.
if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5))
{
await context.CheckpointAsync();
this.checkpointStopWatch.Restart();
}
}
}
I then call this as follows:
EventProcessorHost _eventProcessorHost = new EventProcessorHost(eventProcessorHostName, EndpointName, EventHubConsumerGroup.DefaultGroupName, ConnectionString, storageConnectionString, "messages-events");
await _eventProcessorHost.RegisterEventProcessorAsync<MyEventProcessor>();
I need to pass a parameter to the instance of MyEventProcessor which the EventProcessorHost creates. How would I go about doing this?
You just need to use RegisterEventProcessorFactoryAsync to pass in a factory instance. That factory class can pass in whatever parameters are appropriate in the factory method possibly by passing them into the factory in the first place, or having the factory vary the behavior. In the code sketched out below you can see two parameters being passed into the IEventProcessor. One of them from the factory's parameters and the other is a counter of how many times the factory has been called.
class AzureStreamProcessor : IEventProcessor
{
....
}
class AzureStreamProcessorFactory : IEventProcessorFactory
{
public AzureStreamProcessorFactory(string str)
{
this.randomString = str;
}
private string randomString;
private int numCreated = 0;
IEventProcessor IEventProcessorFactory.CreateEventProcessor(PartitionContext context)
{
return new AzureStreamProcessor(context, randomString, Interlocked.Increment(ref numCreated));
}
}
host.RegisterEventProcessorFactoryAsync(new AzureStreamProcessorFactory("a parameter"), options);
May be try doing a constructor dependency injection to the MyEventProcessor class with a parameter something like below.
public class MyEventProcessor : IEventProcessor
{
Stopwatch checkpointStopWatch;
//TODO: get provider id from parent class
IParameters _parameter;
public MyEventProcessor (IParameters param)
{
this._parameter = param;
}
public async Task CloseAsync(PartitionContext context, CloseReason reason)
{
Debug.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason);
if (reason == CloseReason.Shutdown)
{
await context.CheckpointAsync();
}
}.....
Use _parameter to retrieve what you need.
below is how you can register the dependencies for your IParameters
Here i use Ninject dependency resolver.
//Bind the class that implements IParameter.
var parameters = new Parameter();
paramters.Property = "my data"
kernel.Bind<IParameters>().ToConstant(parameters);
hope that helps
Related
I have a method:
public virtual async Task<IActionResult> GetEmployees([HttpTrigger(AuthorizationLevel.Admin, "get", Route = null)] HttpRequest req) {
return OkObjectResult(null);
}
I know I can intercept this synchronously using autofac:
public class CallLogger : IInterceptor
{
TextWriter _output;
public CallLogger(TextWriter output)
{
_output = output;
}
public void Intercept(IInvocation invocation)
{
_output.Write("Calling method {0} with parameters {1}... ",
invocation.Method.Name,
string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()));
invocation.Proceed();
_output.WriteLine("Done: result was {0}.", invocation.ReturnValue);
}
}
But how can I do this asynchronously while potentially overwriting the result the method I'm intercepting returns? It currently returns an OkObjectResult, I may want to return a 404 instead, for example.
Psuedo Code
public async Task Intercept(IInvocation invocation)
{
var myAsyncResult = await _myAsyncClass.MyAsyncMethod();
if (myAsyncResult == expected)
{
invocation.Proceed();
}
else
{
invocation.ReturnValue = // some overwrite of the value - and don't proceed with the invocation.
}
}
Note
I know there are clever approaches to async in autofac, but this doesn't allow me to prevent execution of the original method and overwrite the value, instead I need to 'proceed' the invocation and use it's return: https://stackoverflow.com/a/39784559/12683473
The main thing to keep in mind with Castle.Core is that you cannot call IInvocation.Proceed after an await because the IInvocation instance is reused after the interceptor (synchronously) returns.
However, modern versions of Castle.Core do support IInvocation.CaptureProceedInfo, which can be used as such:
public class CallLogger : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.ReturnValue = InterceptAsync<MyResult>(invocation.CaptureProceedInfo());
}
private async Task<TResult> InterceptAsync<TResult>(IInvocationProceedInfo proceed)
{
var myAsyncResult = await _myAsyncClass.MyAsyncMethod();
if (myAsyncResult == expected)
{
proceed.Invoke();
}
else
{
return ...;
}
}
}
This simple code assumes your code can specify a type MyResult that is the known result of the intercepted method. The more general case requires reflection and TaskCompletionSource<T>.
I have a microservices architecture using simple injector in each service. The services communicates through Azure Service Bus. I'm currently trying to find a way to implement a generic solution/library for interacting with Azure Service Bus. The library is the core infrastructure of the services and has a topic publisher (for pushing events /messages to azure) and a subscriber (for listening to messages from azure).
Besides that I have a common interface for the events /messages containing an ID and time stamp for creation. I also have a generic interface for event handlers IEventHandler<T> where T : IEvent. Now my problem is, how do I best keep my composition root separated from the rest of the code while still being able to register a set of handlers for the different types of events in a given service?
Reading the docs for simple injector suggests a factory or something like that, but my interface is generic and the factory is not which makes public IEventHandler GetHandler (Type eventType) illegal...
UPDATE: Added code
Publishing:
public interface IEventPublisher
{
Task PublishAsync(IEvent #event);
}
public class EventPublisher : IEventPublisher
{
private readonly ITopicClient topicClient;
public EventPublisher(ITopicClient topicClient)
{
this.topicClient = topicClient;
}
public async Task PublishAsync(IEvent #event)
{
try
{
var json = JsonConvert.SerializeObject(#event);
var message = new Message()
{
Body = Encoding.UTF8.GetBytes(json),
PartitionKey = nameof(#event),
MessageId = #event.Id.ToString()
};
message.UserProperties.Add("Type", #event.GetType().FullName);
await topicClient.SendAsync(message);
}
catch (Exception e)
{
//Handle error
}
}
}
Handling events:
public interface IEventHandler<T> where T : IEvent
{
void HandleEvent(T #event);
}
public interface IEventSubscriber
{
//Currently empty, might need some method for registration of handlers?
}
public class EventSubscriber : IEventSubscriber
{
private readonly ISubscriptionClient subscriptionClient;
public EventSubscriber(ISubscriptionClient subscriptionClient, )
{
this.subscriptionClient = subscriptionClient;
var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
{
AutoComplete = false
};
this.subscriptionClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
}
private Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
{
var context = exceptionReceivedEventArgs.ExceptionReceivedContext;
logger.Error($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}.");
logger.Error("Exception context for troubleshooting:");
logger.Error($"- Endpoint: {context.Endpoint}");
logger.Error($"- Entity Path: {context.EntityPath}");
logger.Error($"- Executing Action: {context.Action}");
return Task.CompletedTask;
}
private async Task ProcessMessagesAsync(Message message, CancellationToken cancellationToken)
{
JsonConvert.DeserializeObject<BankDataChangedEvent>(Encoding.UTF8.GetString(message.Body));
// HERE I NEED SOME CODE TO FETCH/FIND THE RIGHT HANDLER FOR THE EVENT TYPE
await subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
}
}
Most of the pulisher and subscriber are boilerplate code from Microsoft docs for Azure Service Bus with .Net - only slightly modified.
Maybe I know what do you want.
Do you have something like this?
internal sealed class CommonEventConsumer :
IConsumer<Event1>,
IConsumer<Event2>
{
private readonly ISomeService _someService;
public CommonEventConsumer(ISomeService someService)
{
_someService = someService;
}
public async Task HandleEventAsync(Event1 eventMessage)
{
await _someService.DoSomeThing1(eventMessage);
}
public async Task HandleEventAsync(Event2 eventMessage)
{
await _someService.DoSomeThing2(eventMessage);
}
}
where IConsumer<Tevent> is global interface which has method HandleEventAsync(Tevent event message); and CommonEventConsumer is average consumer in any of your microservice.
Also the publisher is like:
public sealed class EventPublisher : IEventPublisher
{
public async Task PublishAsync<T>(T eventMessage)
{
var subscriptions = DependencyResolver.ResolveAll<IConsumer<T>>();
foreach (var subscription in subscriptions)
{
await subscription.HandleEventAsync(eventMessage);
}
}
}
where I resolve all event subscribers and push messages to them.
If yes, then I have the same structure in my application, and my SimpleInjector registration for eventConsumers look's like that:
private static void RegisterConsumers(Container container)
{
container.Register<IEventPublisher, EventPublisher>(Lifestyle.Scoped);
container.Collection.Register(typeof(IConsumer<>), new[] {
typeof(CommonConsumer),
typeof(MeasurementEventConsumer),
typeof(PartRepairEventConsumer),
typeof(OrderItemEventConsumer),
typeof(OrderTaskEventConsumer),
typeof(OrderItemWorkStatusEventConsumer),
typeof(OrderItemTaskEventConsumer),
typeof(OrderTaxEventConsumer)
});
}
I am using azure event hub and I am trying to work out how pass in dependencies into the EventProcessor class used to process events off the event hub in my worker role. This class inherits the .net interface IEventProcessor.
My event processor class is shown below. I am struggling using structure map to inject the OrchestrationService and its dependancies in through constructor injection.
Any suggestions will be gratefully accepted :-)
public class EventHubEventProcessor : IEventProcessor
{
private readonly IOrchestrationService _orchestrationService;
private readonly IEventReceiver _eventReceiver;
IDictionary<string, int> map;
PartitionContext partitionContext;
Stopwatch checkpointStopWatch;
public EventHubEventProcessor(IOrchestrationService orchestrationService)
{
_orchestrationService = orchestrationService;
}
public Task OpenAsync(PartitionContext context)
{
Console.WriteLine(string.Format("SimpleEventProcessor initialize. Partition: '{0}', Offset: '{1}'", context.Lease.PartitionId, context.Lease.Offset));
this.partitionContext = context;
this.checkpointStopWatch = new Stopwatch();
this.checkpointStopWatch.Start();
return Task.FromResult<object>(null);
}
public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events)
{
try
{
foreach (EventData eventData in events)
{
_orchestrationService.Orchestrate(eventData);
Console.WriteLine("Processed Event " + eventData.PartitionKey);
}
//Call checkpoint every 5 minutes, so that worker can resume processing from the 5 minutes back if it restarts.
if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5))
{
await context.CheckpointAsync();
this.checkpointStopWatch.Restart();
}
}
catch (Exception exp)
{
Console.WriteLine("Error in processing: " + exp.Message);
}
}
public async Task CloseAsync(PartitionContext context, CloseReason reason)
{
Console.WriteLine(string.Format("Processor Shuting Down. Partition '{0}', Reason: '{1}'.", this.partitionContext.Lease.PartitionId, reason.ToString()));
if (reason == CloseReason.Shutdown)
{
await context.CheckpointAsync();
}
}
}
}
Perhaps you need to implement IEventProcessorFactory:
https://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.ieventprocessorfactory.aspx
...and pass an instance of that into EventProcessorHost.RegisterEventProcessorFactoryAsync():
https://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.eventprocessorhost.registereventprocessorfactoryasync.aspx
That way your factory can handle the StructureMap magic and inject OrchestrationService as needed.
Apart from .NET 4.5.1 there is a new option on the TransactionScope which enables to use async flow. This allows to write the following client code
using(var txt = new TransactionScope(..., TransactionScopeAsyncFlowOption.Enabled)
{
await sender.SendAsync();
}
So far so good. But when I need to implement a volatile IEnlistmentNotification I'm struggling to do that. Let's imagine the following scenario, assumption: My underlying infrastructure is completely async from bottom to top
public class MessageSender : ISendMessages
{
public async Task SendAsync(TransportMessage message, SendOptions options)
{
await sender.SendAsync(message);
}
}
So what I want to achieve is to introduce a volatile IEnlistmentNotification like this:
internal class SendResourceManager : IEnlistmentNotification
{
private readonly Func<Task> onCommit;
public SendResourceManager(Func<Task> onCommit)
{
this.onCommit = onCommit;
}
public void Prepare(PreparingEnlistment preparingEnlistment)
{
preparingEnlistment.Prepared();
}
public void Commit(Enlistment enlistment)
{
await this.onCommit();
enlistment.Done();
}
public void Rollback(Enlistment enlistment)
{
enlistment.Done();
}
public void InDoubt(Enlistment enlistment)
{
enlistment.Done();
}
}
and the new sender
public class MessageSender : ISendMessages
{
public async Task SendAsync(TransportMessage message, SendOptions options)
{
// Dirty: Let's assume Transaction.Current is never null
Transaction.Current.EnlistVolatile(new SendResourceManager(async () => { await sender.SendAsync(message) }));
}
}
Note: Of course this code doesn't compile. It would require me to declare the commit method async void. Which is aweful.
So my question is: How can I write an enlistment which can internally await an asynchronous operation?
As long as EnlistVolatile isn't a heavy CPU bound time consuming operation, you can create a thin Task based wrapper over EnlistVolatile using Task.FromResult:
public static class TranscationExtensions
{
public static Task EnlistVolatileAsync(this Transaction transaction,
IEnlistmentNotification
enlistmentNotification,
EnlistmentOptions enlistmentOptions)
{
return Task.FromResult(transaction.EnlistVolatile
(enlistmentNotification,
enlistmentOptions));
}
}
and then consume it inside your method:
public class MessageSender : ISendMessages
{
public Task SendAsync(TransportMessage message, SendOptions options)
{
return Transaction.Current.EnlistVolatileAsync
(new SendResourceManager(async () =>
{ await sender.SendAsync(message) }));
}
}
which can be awaited higher in your callstack:
MessageSender sender = new MessageSender();
await sender.SendAsync(message, options);
I have a kind of bus that implements this interface:
public interface IBus
{
void Publish<T>(T t);
void Subscribe<T>(Guid subscriptionId, Action<T> action);
void Unsubscribe<T>(Guid subscriptionId);
}
Here is an example on how I use it:
public void PrintName()
{
IBus bus = new Bus();
var id = Guid.NewGuid();
bus.Subscribe<ReplyUserName>(id, replyUserName =>
{
bus.Unsubscribe<ReplyUserName>(id);
Console.WriteLine(replyUserName.UserName);
});
Bus.Publish(new RequestUserName());
}
And here are the RequestUserName and ReplyUserName classes:
public class RequestUserName {}
public class ReplyUserName
{
public string UserName { get; set; }
}
However I would like to write an extension method that would wrap this with async:
public static class BusExtension
{
public static async Task<TResult> Request<TRequest, TResult>(this IBus bus, TRequest request)
{
// TODO...
}
}
So that I will be able to write the previous code in such a way:
public async void PrintName()
{
IBus bus = new Bus();
var replyUserName = await bus.Request<RequestUserName, ReplyUserName>(new RequestUserName());
Console.WriteLine(replyUserName.UserName);
}
what should I write instead of the TODO?
You can use TaskCompletionSource<T> to wrap anything into an await-compatible method.
public static Task<TResult> Request<TRequest, TResult>(this IBus bus, TRequest request)
{
var tcs = new TaskCompletionSource<TResult>();
var id = Guid.NewGuid();
bus.Subscribe<TResult>(id, result =>
{
bus.Unsubscribe<TResult>(id);
tcs.TrySetResult(result);
});
bus.Publish(request);
return tcs.Task;
}
Note, however, that you should ensure that the task is completed. If there's any chance that the bus won't respond to the request, you should have a timer or something that faults the TaskCompletionSource.
You could implement this as follows:
var taskCompletionSource = new TaskCompletionSource<TResult>();
bus.Subscribe<TResult>(id, result =>
{
bus.Unsubscribe<TResult>(id);
taskCompletionSource.SetResult(result);
});
bus.Publish(request);
return taskCompletionSource.Task;
You might also want to check out Reactive Extensions (Rx) as your IBus interface looks similar to the ISubject interface (http://msdn.microsoft.com/en-us/library/hh211669.aspx). The Reactive Extensions library already provides convenient extension methods similar to the one you are attempting to implement.