How do you register a behavior to execute after the "Handle" method in NServiceBus 6? - nservicebus

I have an Endpoint with a Handle method. I would like to do something immediately before and immediately following Handle. I was able to get the step working before by imolementing LogCommandEntryBehavior : Behavior<IIncomingLogicalMessageContext>. What needs to be implemented to happen immediately following Handle?

In NServiceBus Version 6, the pipeline consists of a series of Stages, each one nested inside the previous like a set of Russian Dolls. For an incoming message, the stages are (in order):
ITransportReceiveContext,
IIncomingPhysicalMessageContext,
IIncomingLogicalMessageContext, and
IInvokeHandlerContext
When you create a behavior within a stage, you get passed a delegate called next(). When you call next() you execute the next behavior in the pipeline (which may move the pipeline to the next stage). The call to next() returns a Task which indicates when this inner part of the pipeline is done.
That gives you the opportunity to invoke your code before moving on to the next stage, and invoke more code after the next stage has been completed like this:
public class LogCommandEntryBehavior : Behavior<IIncomingLogicalMessageContext>
{
public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next)
{
// custom logic before calling the next step in the pipeline.
await next().ConfigureAwait(false);
// custom logic after all inner steps in the pipeline completed.
}
}
If you want to log information about the handling of a message, I recommend looking at the IInvokeHandlerContext stage. It contains information about how the message was handled and will be called once for every handler that is invoked (in cases where you have multiple). If you don't need info at that level then IIncomingLogicalMessageContext is probably all you need.
You can read more about the Version 6 pipeline in the Particular Docs site:
Steps, Stages and Connectors
Manipulate Pipeline with Behaviors

Related

Axon & CompletableFuture

I've faced with problems when i try to use CompletableFuture with Axon.
For example:
CompletableFuture future = CompletableFuture.supplyAsync(() -> {
log.info("Start processing target: {}", target.toString());
return new Event();
}, threadPool);
future.thenAcceptAsync(event -> {
log.info("Send Event");
AggregateLifecycle.apply(event);
}, currentExecutor);
in thenAcceptAsync - AggregateLifecycle.apply(event) has unexpected behavior. Some of my #EventSourcingHandler handlers start handling event twice. Does anybody know how to fix it?
I have been reading docs and everything that i got is:
In most cases, the DefaultUnitOfWork will provide you with the
functionality you need. It expects processing to happen within a
single thread.
so, it seems i should use somehow CurrentUnitOfWork.get/set methods but still can't understand Axon API.
You should not apply() events asynchronously. The apply() method will call the aggregate's internal #EventSourcingHandler methods and schedule the event for publication when the unit of work completes (successfully).
The way Axon works with the Unit of Work (which coordinates activity of a single message handler invocation), the apply() method must be invoked in the thread that manages that Unit of Work.
If you want asynchronous publication of Events, use an Event Bus that uses an Async Transport, and use Tracking Processors.

ViewComponent InvokeAsync method and non async operation

In asp.net core ViewComponent we have to implement logic in an InvokeAsync method that returns an IViewComponentResult. However I do not have any async logic to perform inside the invoke method. So based on SO post here I have removed the async qualifier and just return Task.FromResult
public Task<IViewComponentResult> InvokeAsync(MyBaseModel model)
{
var name = MyFactory.GetViewComponent(model.DocumentTypeID);
return Task.FromResult<IViewComponentResult>(View(name, model));
}
and then in View ( since I don't have async I am not using await here)
#Component.InvokeAsync("MyViewComponent", new { model = Model })
However view renders this:
System.Threading.Tasks.Task1[Microsoft.AspNetCore.Html.IHtmlContent]`
You must await the Component.InvokeAsync. The fact that your method doesn't do anything async doesn't matter. The method itself is async.
However, that's a bit of an oversimplification. Frankly, the ease of the async/await keywords belies how complicated all this actually is. To be accurate, instead of calling these types of methods "async", it's more appropriate to discuss them as "task-returning". A task is essentially a handle for some operation. That operation could be async or sync. It's most closely associated with async, simply because wrapping sync operations in a task would be pretty pointless in most scenarios. However, the point is that just because something must return a task does not also imply that it must be async.
All async does is allow the possibility of a thread switch. In scenarios where there's some operation, typically involving I/O, that would cause the working thread to be idle for some period of time, the thread becomes available to be used for other work, and the original work may complete on a different thread. Notice the use of the passive language here. Async operations can involve no thread switching; the task could complete on the same thread, as if it was sync. The task could even complete immediately, if the underlying operation has already completed.
In your scenario here, you're not doing any async work, which is fine. However, the method definition requires Task<T> as the return, so you must use Task.FromResult to return your actual result. That's all pretty standard stuff, and seems to be understood already by you. What you're missing, I think, is that you're thinking that since you're not actually doing any asynchronous work, it would be wrong to utilize await. There's nothing magical about the await keyword; it basically just means hold here until the task completes. If there's no async work to be done, as is the case here, the sync code will just run as normal and yield back to the calling code when done, However, as a convenience, await also performs one other vital function: it unwraps the task.
That is where your problem lies. Since you're not awaiting, the task itself is being returned into the Razor view processing pipeline. It doesn't know what to do with that, so it does what it does by default and just calls ToString on it, hence the text you're getting back. Unwrapped, you'd just have IViewComponentResult and Razor does know what to do with that.
If your logic performed inside the invoke method is synchronous, i.e., you don't have any await, you have 2 options:
You can define invoke method without async keyword and it should return Task.FromResult<T>
Use public IViewComponentResult Invoke() instead.
I think the async keyword enables the await keyword and that's pretty much about it. Nothing special about async keyword.
On the main thread where your view is getting rendered, since the tag helper method
to invoke a view component Component.InvokeAsync() is awaitable, you do need to put await keyword there to start the task. await examines the view component rendering to see if it has already completed. If it has, then the main thread just keeps going. Otherwise the main thread will tell the ViewComponent to run.

Triggering non-interrupting boundary event with variables

My question is about the Camunda API method RuntimeService#messageEventReceived(java.lang.String, java.lang.String, java.util.Map<java.lang.String,java.lang.Object>). We use this method to trigger a non-interrupting boundary message event (on a receive task that is waiting for a different message), like this. As third parameter in the method call, we are passing some process variables.
As expected, this leaves the receive task active and starts a new execution leaving the boundary event. I would have expected that the process variables passed to the third argument of RuntimeService#messageEventReceived would now be stored in the newly created execution, but it seems to be the case that they are stored in the execution of the receive task. This does not make much sense to me, because this is not the execution that "resulted" from the message.
We can workaround this problem by determining which execution is new after the execution of RuntimeService#messageEventReceived and attaching process variables there manually. But this does not seem very elegant - does anyone know a better solution? Or am I misunderstanding something?
This is expected behavior, see the java doc of the method
void messageEventReceived(String, String, Map)
void messageEventReceived(String messageName,
String executionId,
Map<String,Object> processVariables)
Notifies the process engine that a message event with the name 'messageName' has been received and has been correlated to an execution with id 'executionId'. The waiting execution is notified synchronously. Note that you need to provide the exact execution that is waiting for the message if the process instance contains multiple executions.
Parameters:
messageName - the name of the message event
executionId - the id of the process instance or the execution to deliver the message to
processVariables - a map of variables added to the execution
Since the process variables are set on the existing execution they are also available on the new created child execution.
As alternative you could create a ServiceTask after the Boundary event, which creates the process variables OR you create another ReceiveTask after the Boundary event. This receive task could be completed with your message and the needed variables.

Manually Persisting to Instance table as like PersistableIdleAction.Unload

I have a workflow inside a transaction so the code in this is hanging on WaitOne() call where I am calling context.CreateBookmark method.
Since the workflow in not completed (syncEvent.set() is not called) transaction is not getting completed.
But I want to persist the workflow execution until the bookmark part, if I do that by calling syncEvent.Set() on
wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
{
idleEvent.Set();
return PersistableIdleAction.Persist;
};
it is not creating a record in InstanceTable. So I want to persist the workflow manually to InstaceTable or a better way to implement this.
I am using flowchart type workflow
Use the Unloaded event to syncEvent.Set()

how to cancel WCF service call?

I have a WCF function that is executing long time, so I call the function in UI with backgraundworker... I want to give a feature to cancel the execution, so I abort IComunicationObject, the problem is that Service execution is not stoping, Is there any way to stop Service execution in this case?
You may not need a BackgroundWorker. You can either make the operation IsOneWay, or implement the asynchronous pattern. To prevent threading issues, consider using the SynchronizationContext. Programming WCF Services does a great job at explaining these.
Make a CancelOperation() method which sets some static ManualResetEvent in your service. Check this event in your Operation method frequently. Or it can be CancelOperation(Guid operationId) if your service can process multiple operation calls concurrently.
One important thing to understand if you're using the Async calls is that there's still no way to cancel a request and prevent a response coming back from the service once it's started. It's up to your UI to be intelligent in handling responses to avoid race conditions. Fortunately there's a simple way of doing this.
This example is for searching orders - driven by a UI. Lets assume it may take a few seconds to return results and the user is running two searches back to back.
Therefore if your user runs two searches and the first search returns after the second - you need to make sure you don't display the results of the first search.
private int _searchRequestID = 0; // need one for each WCF method you call
// Call our service...
// The call is made using the overload to the Async method with 'UserToken'.
// When the call completes we check the ID matches to avoid a nasty
// race condition
_searchRequestID = _searchRequestID++;
client.SearchOrdersCompleted += (s, e) =>
{
if (_searchRequestID != (int)e.UserState))
{
return; // avoid nasty race condition
}
// ok to handle response ...
}
client.SearchOrdersAsync(searchMessage, _searchRequestID);