I have a handler which, when it handles some event, sends a request and, depending on the reply, might publish an alert. I'm trying to test this using the NServiceBus Testing framework, but can't quite see how to pretend the bus is replying. I've seen examples of how to test send (using Test.Handler(...).ExpectSend...) and how to test reply in the other handler that is doing the reply (using Test.Handler(...).ExpectReply), but nothing about stubbing the reply to test the handling of the reply.
Here's what my handler's Handle method looks like:
public void Handle(SomeEvent #event)
{
bus.Send<SomeRequest>(request => { request.Stuff = #event.Stuff })
.Register<SomeReply>(reply => { if (reply.OhNo) bus.Publish(new SomeAlert("augh!")); });
}
And here's what the test looks like so far:
Test.Handler(bus => new MyHandler(bus, serviceMock.Object)).
ExpectSend(verifyRequest).
// thought maybe something here like .StubReply(someReply) or something?
ExpectPublish(verifyAlert).
OnMessage(#event, "xyz");
Thanks for any advice!
Message handlers are single call objects with no state, so the call to .Register won't work as you expect. You could move the reply handling logic to a separate message handler (as it doesn't appear like you have any behavior that depends on remembering something from the request) or you could use a saga if you need a more involved orchestration.
Incidentally, you wouldn't use .Register with your sagas either - instead you'd have a separate Handle method for the response. They also have a more complete testing API, though I wouldn't consider that an argument for using them in this case.
Start with a separate handler for your response message type.
Related
Updated below...
So this is a random question that came about from a discussion over what I consider the over usage of await in projects at work...
Not sure why I never tried it until now, other than the fact that it's weird and random, but the fact it does work just makes me wonder...how?
The .Result usage was only used to get the responseMessage. I know that is blocking and no bueno and it is for demo purposes only...
So this endpoint works fine...nothing is awaited
[HttpGet("kitteh")]
public Task<string> GetCatFact()
{
var client = new HttpClient();
var res = client.GetAsync("https://catfact.ninja/fact").Result;
return res.Content.ReadAsStringAsync();
}
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result...but where...or how?
Is this "less efficient" than awaiting in the endpoint itself as the magic taking place behind the scenes is ultimately just blocking to get the result of the returned task?
Updated
So, I am still skeptical and don't think the answer is as easy as "yes it is blocking" or "not it is not blocking" unless there's some legit proof or something to indicate one way or the other. I tried digging through the code myself, and I still don't have a solid answer but...I do know more than I did before...
I simplified the endpoints I have been testing this with...
[HttpGet("taskstring")]
public Task<string> TaskString()
{
return Task.FromResult("Where does this block?");
}
[HttpGet("asyncstring")]
public async Task<string> AsyncString()
{
return await Task.FromResult("This definitely doesn't block");
}
I stepped through a bunch of code and ultimately landed on ObjectMethodExecutor and AwaitableObjectResultExecutor which sparked some interest.
What appears to happen for both the endpoint versions above is the same or nearly the same, at least the execution of these two endpoints and the code covered below. There's a boatload that goes on during this and even though the rider debugger is great, it's not possible to see a lot of the values while debugging due to "Evaluation is not allowed: The thread is not at a GC-safe point".
When the endpoint is called but prior to the endpoint beginning execution...
ObjectMethodExecutor.ctor is called
This does a lot of inspection of the endpoint to determine a bunch of things
One of the checks is to is determine if the method is "async" and it ultimately calls AwaitableInfo.IsTypeAwaitable to check for the required methods/properties and interfaces to ensure it is
If it is, which in the case of returning Task of string it is, makes sense given the above info
ObjectMethodExecutor.GetExecutorAsync() is called
AwaitableObjectResultExecutor.Execute is then called
this type inherits ActionMethodExecutor which overrides the Execute method
executor.ExecuteAsync(executor type of ObjectMethodExecutorAwaitable) is then called, and awaited
this returns a result of type object, boxing yeah I know
The endpoint then actually executes and returns to AwaitableObjectResultExecutor.Execute
the result is then passed to ConvertToActionResult along with the return type, the T of Task of T and the mapper implementation
the mapped ActionResult is then returned
So...I'm still not certain 100% either way but there is a lot of effort put into inspecting the endpoint that is being called and determining if it's async or not, which would make it seem logical to think this is an attempt to avoid something...maybe blocking?
So...does it block...maybe? Seeing that there is an await from the indirect caller of the endpoint, I'd lean towards, no...but it seems really difficult to say still.
What I do now know is...
It definitely does await the endpoint call, albeit indirectly
It converts the Task of string return type to an IActionResult
An async and task only version seem to follow the exact some flow shown above
A non async version does not
So, based on all of that...#Phil's answer seems to be pretty spot on with what I found...
"The framework supports asynchronous controller actions. In order to do so, it would need to inspect the return value of your methods. If the method returns a Task, it will ultimately await on the result before responding.
Even if your action itself does all the awaiting, it still has to return a Task so the caller will still wait (the alternative being some ugly blocking code)."
Thanks to all for participating in an extremely random question that doesn't hold much value to truly understand
Your assumption here is basically correct...
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result
The framework supports asynchronous controller actions. In order to do so, it would need to inspect the return value of your methods. If the method returns a Task, it will ultimately await on the result before responding.
Even if your action itself does all the awaiting, it still has to return a Task so the caller will still wait (the alternative being some ugly blocking code).
As has been pointed out in some other posts, there are some performance improvements to be had by not awaiting a returned Task so I would write your action as
public async Task<string> GetCatFact()
{
var client = new HttpClient();
var res = await client.GetAsync("https://catfact.ninja/fact");
return res.Content.ReadAsStringAsync(); // no await
}
Your controller handles waiting for the remote response but delegates waiting for the content stream to the caller.
There's obviously something in the default ASP.NET pipleline that ultimately unwraps the task in order to return the result...but where...or how?
ASP.NET asynchronously waits for your task to complete, and then it sends the HTTP response based on the result of the task. It's logically similar to await: an asynchronous wait.
Is this "less efficient" than awaiting in the endpoint itself as the magic taking place behind the scenes is ultimately just blocking to get the result of the returned task?
Yes. It is less efficient to block.
ASP.NET doesn't block; it asynchronously waits. Blocking ties up a thread. So when the code calls .Result, it will be using a thread just to wait for that HttpClient call to complete.
The proper solution is to keep async and await:
[HttpGet("kitteh")]
public async Task<string> GetCatFact()
{
var client = new HttpClient();
var res = await client.GetAsync("https://catfact.ninja/fact");
return await res.Content.ReadAsStringAsync();
}
This way, while the GetAsync is in progress, the thread is yielded back to the ASP.NET runtime and is available for handling other requests, instead of being blocked waiting for the GetAsync to complete.
More information: Task<string> is part of the method signature. ASP.NET has special understanding of the Task<T> type and knows to asynchronously wait for it. async is not part of the method signature. ASP.NET knows whether your method returns Task, but it has no idea whether it's async (and doesn't care). So, in some situations, it's OK to elide the keywords (as described on my blog, but only when the method implementation is trivial. If there's any logic in the method, keep the async and await.
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.
I have read multiple times the documentation on the website. I am reading again and again the same articles and I cannot understand what they are trying to achieve with sagas. Besides, there are almost no resources in internet related to this subject.
But I am completely stuck trying to understand the purpose and benefit of defining so called sagas. I understand handlers (IHandleMessages) - these are interceptors. But I can't understand what Saga is for. The language in the documentation assumes that I am supposed to know something special to grasp that idea, but I dont.
Can someone explain to me in simple words, hopefully with real-life example a situation where I must or should define Saga, and what is the benefit of doing so? I have created an app with multiple endpoints and Saga definition as shown in samples, it works (I guess) but I don't understand what these sagas were defined for... In many samples they use RequestTimeout() method in Saga class. Why, why would anyone want to cause a timeout intentionally? I dont want to put any code fragments here, because its unrelated, I need to understand why I would want to use "Sagas" whatever that means?
Thank you.
NServiceBus Saga is a variant of a Process Manager described in the Enterprise Integration Patterns book.
To understand when to use Saga, one has to need it. Let's assume you're using regular message handlers only to implement new user registration process. At some point in time, you discover that only 40% of the brand-new registrants confirm their email address and becoming active user accounts. There are two things you'd like to address.
Remind new registrants to confirm their email after 24 hours after registration by sending a reminder.
Remove registrant info (email for example) from the data store to be compliant with GDPR within 48 hours.
Now how do you do that with a regular message handler? A handler would receive the initial request (first message, m1) to kick off registration by generating an email with a confirmation link and that's it. Once the handler is done, it's done for good. But your process is not finished. It's a long-running logical process that has to span 48 hours before completed. It's no longer just a single message processing, but a workflow at this point. A workflow with multiple checkpoints. Similar to a state machine. To move from one state to another, a certain condition has to be fulfilled. In case of NServiceBus, those would be messages. A message to send a reminder after 24 hours (let's call it m2) is not going to be triggered by any user action. It's a "system" message. A timed message that should be kicked off automatically. So is with the message to instruct the system to remove registrant information if validation link was not activated. The theme can be observed: need to schedule messages in the future to re-hydrate the workflow and continue from the state it was left last time.
That's what timeouts are. Those are requests to re-hydrate/continue saga/workflow from the point it was left last time at a certain point in time - minutes, hours, days, months, years.
This is what this kind of workflow would look like as a saga (oversimplified and doesn't take into consideration all the edge cases).
class RegistrationWorkflow :
Saga<WorkflowState>,
IAmStartedByMessages<RegisterUser>,
IHandleMessages<ActivationReceived>,
IHandleTimeouts<NoResponseFor24Hours>,
IHandleTimeouts<NoResponseFor48Hours>
{
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<WorkflowState> mapper)
{
// omitted for simplicity, see message correlation
// https://docs.particular.net/nservicebus/sagas/message-correlation
}
public async Task Handle(RegisterUser message, IMessageHandlerContext context)
{
Data.RegistrationId = message.RegistrationEmail;
await RequestTimeout<NoResponseFor24Hours>(context, TimeSpan.FromHours(24));
}
public async Task Handle(ActivationReceived message, IMessageHandlerContext context)
{
Data.ConfirmationReceived = true;
// email was confirmed and account was activated
await context.Send(new PromoteCandidateToUser
{
CandidateEmail = Data.RegistrationEmail
});
MarkAsComplete()
}
public async Task Timeout(NoResponseFor24Hours timeout, IMessageHandlerContext context)
{
if (Data.ConfirmationReceived)
{
return;
}
await context.Send(new SendReminderEmailToActivateAccount { Email = Data.RegistrationEmail });
await RequestTimeout(context, TimeSpan.FromHours(24), new NoResponseFor48Hours());
}
public async Task Timeout(NoResponseFor48Hours timeout, IMessageHandlerContext context)
{
if (Data.ConfirmationReceived)
{
return;
}
context.Send(new CleanupRegistrationInformationForGDPRCompliancy
{
RegistrationEmail = Data.RegistrationEmail
});
MarkAsComplete();
}
}
Since this is a state machine, the state is persisted between Saga invocations. Invocation would be caused either by a message a saga can handle (RegisterUser and ActivationReceived) or by timeouts that are due (NoResponseFor24Hours and NoResponseFor48Hours). For this specific saga, the state is defined by the following POCO:
class WorkflowState : ContainSagaData
{
public string RegistrationEmail { get; set; }
public bool ConfirmationReceived { get; set; }
}
Timeouts are nothing but plain IMessages that get deferred. The timeouts used in this samples would be
class NoResponseFor24Hours : IMessage {}
class NoResponseFor48Hours : IMessage {}
Hope this clarifies the idea of Sagas in general, what Timeouts are and how they are used. I did not go into Message Correlation, Saga Concurrency, and some other details as those can be found at the documentation site you've referred to. Which bring us to the next point.
I have read multiple times the documentation on their website. It is absolutely terrible. I am reading again and again the same articles and I cannot comprehend what they are trying to achieve.
The site has a feedback mechanism you should absolutely provide.
Besides there almost no resources in internet related to this subject.
Hope to see you posting a blog (or a series of posts) on this topic. By doing so you'll have a positive contribution.
Full disclaimer: I work on NServiceBus
Currently, we are using StackExchange.Redis and, as it does not provides "blocking pops", we are doing as suggested on the documentation:
db.ListLeftPush(key, newWork, flags: CommandFlags.FireAndForget);
sub.Publish(channel, "");
What is the difference from this to the following?
db.ListLeftPushAsync(key, newWork);
sub.Publish(channel, "");
We know the purpose of the commands, what we would like to know is if it has any difference internally or any risk of behaving differently? (Execution order etc.)
There's a main difference comparing fire and forget vs calling an async operation and not awaiting it.
Fire and forget means that not only you're not waiting for the result but you don't care if it works or not, while an async operation may throw an exception once it has ended if something goes wrong.
In the other hand, when you issue a fire and forget command, StackExchange.Redis doesn't try to retrieve the command result internally, which is better if you just want the so-called fire and forget behavior when issuing commands.
You may check this difference if you open ConnectionMultiplexer source code and you see how ExecuteAsyncImpl / ExecuteSyncImpl methods are implemented:
// For example, ExecuteAsyncImpl...
if (message.IsFireAndForget)
{
TryPushMessageToBridge(message, processor, null, ref server);
return CompletedTask<T>.Default(null); // F+F explicitly does not get async-state
}
else
{
var tcs = TaskSource.CreateDenyExecSync<T>(state);
var source = ResultBox<T>.Get(tcs);
if (!TryPushMessageToBridge(message, processor, source, ref server))
{
ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(IncludeDetailInExceptions, message.Command, message, server));
}
return tcs.Task;
}
Answer to some OP comment
Hi. Thanks for your answer. We know the purpose of the commands, what
we would like to know is if it has any differrence internally or any
risk of behaving differently (execution order etc.)
Since the async operation won't be finished when you publish the message on the Redis channel, it can happen that you publish the message and the operation gets executed never. You lose a lot of control.
When you send a fire and forget command, it mightn't be executed too, but you know that the try was done before you publish the channel's message. Therefore, you shouldn't use async operations to implement fire and forget pattern when using StackExchange.Redis.
You may check this other related Q&A: Stackexchange.redis does fire and forget guarantees delivery?
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);