How to prevent unintended flagging of suppressed scope transaction in NServiceBus? - nservicebus

I'm trying to send a simple message, but it seems like it automatically gets flagged as not having a transaction scope (behavior).
The endpoint is running the SQL transport (3.0.1) and NSB 6.1.2, SQL transport runs in default transaction mode (TransactionScope).
As far as I'm aware, no specific action has been taken for this, the only thing I can imagine is that the connection string is shared with Dapper who executed a couple of awaited queries to the database too.
var data = await Provider.GetSomeRandomData(message.DataId);
bool synced = false;
await context.Reply(new RandomMessage());
If the endpoint is configured using TransportTransactionMode.SendsAtomicWithReceive nothing is logged, when TransportTransactionMode.TransactionScope is enabled, the logging occurs (and of course presumably also the actual effect is lost).
Ideally, the provider would use (somehow) the same transaction NServiceBus is using, though for querying data it'd need to somehow break out of this transaction context, query the database without breaking the NServiceBus transaction (if this is actually the problem), so that writes would still be transacted.

Can you try and add .ConfigureAwait(false)
await context.Reply(new RandomMessage())
.ConfigureAwait(false);
See this article for more details
Does that resolve the issue?

Related

Remove TransactionScopeRequired = true

I have an operation contract, on a windows service and it has an attribute
[OperationBehavior(TransactionScopeRequired = true)]
I would like to get rid of this attribute. Reason :
containerize the service.
and Containerized apps do not support MSDTC , that's the purpose of the attribute!
What are the implications of doing this?
I can confirm the code within the operation contract inserts into a single database.
No events triggered, however I am unsure of whether there is a transaction where the service is consumed.
Can I get some advice on this?
Your service is requiring a transaction.
Only you can know whether this is necessary, we cannot check your service and database to check.
Please be aware that this enables not only local transactions, but -depending on binding- also enables distributed transactions. See here for details.
You new system does not seem to support this (MSDTC is the Distributed Transaction Controller from MS). Again, whether this is a problem when you move over to this system is nothing we could find out. You will have to have a look at the system architecture and see whether this is something that was included "just because" and can be deleted without replacement, or if it's a key feature of your system that you need to keep.

What approach is there for handling and returning errors (non-exceptional and exceptional) in Domain Driven Design entities and aggregate roots?

I'm trying to find a good article/examples of how DDD entities treat errors (and what would be considered exceptional errors and what wouldn't) and how they pass them up to the calling application layer (which usually wraps operations in a transaction that would need to be rolled back).
Currently I'm thinking to consider all errors that would break the transaction of an aggregate (such as validation) to be exceptions. This way I can rollback the transaction in a "catch" block. For example:
SomeApplicationService:
// start transaction here
// ...
try
{
$user = $userRepository->userOfId($id);
$user->doSomething();
$user->doSomethingElse(); // <-- imagine an error thrown here
$userRepository->save($user);
}
catch (CustomFriendlyForUIException $e)
{
// Custom Friendly for UI error
// Rollback transaction and add error/message to UI payload DTO
// ...
}
catch (AnotherCustomException $e)
{
// Not friendly to UI, so use general error message for UI
// Rollback transaction and add error/message to UI payload DTO
// ...
}
catch (Exception $e)
{
// Catch all other exceptions, use general error message for UI
// Rollback transaction and add error/message to UI payload DTO
// ...
}
// end transaction
Is this the correct approach, or am I missing something?
Usually, there are two types of error:
business errors that have a business meaning. For instance, StockFullError, ProductNotAvailableError, etc. These errors are expected because they are explicitly created in the code.
These kind of error can be implemented using exceptions or using the
functional way: explicitly show errors in the return type. For
instance: Either<Error, T>.
Exception make the code simpler. Handling error the functional programming way make the code easier to reason about and more predictable. I would advise the latter.
infrastructure errors are errors linked to the database, network, external services, etc. These error are usually unexpected.
Error happen. And when error happen, you don't want the application to be in an inconsistent state. For instance, you want to avoid to have half of the aggregate stored in the datastore.
Aggregate integrity
The key problem here is to maintain the aggregate integrity. The critical point is when the aggregate has to be written in the datastore. I can see two situations:
The operation to persist the aggregate is atomic
As soon as your datastore can provide atomic operations, there is no worry to have about the data integrity because the result of an atomic operation is either a failure or a success. There is no partial writes.
That means that you can just let your http layer handle exception and return 500 for instance.
The operation to persist the aggregate is not atomic
Sometimes, ensuring atomicity is not possible.
One aggregate in several tables
If you need to store your aggregate in several tables, there are some solutions:
Transactions. Surrounding the code in a transaction could be a solution. However transactions have some disadvantages. If the computation is too long or if this part of the code is called too often, it would slow down the application.
Unit Of Work is an old pattern. The idea is to register operations that you want to do: add, update, delete, etc. Eventually, UOW applies the changes to the database using a transaction. See Fowler's article for more information.
SAGAs: sometimes a big transaction is not possible
When you send an email and save something in the database, you can't include the email in the transaction.
In that case, you can use SAGAs. The idea is that, sometime, you can't have one single big transaction to enforce atomicity. However, it is usually easy to have several small transactions.
The idea of a SAGA is to associate every single transaction to a compensating transaction. For instance given the "transaction": send an email to confirm that the product is bought, the compensating "transaction" could be sent an email to apologise with a coupon.
Every transaction small transaction is run. If one of these fails, compensating transaction are run. Eventually, this enables to get atomicity.

Difference between FireAndForget and Async behavior for publishing

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?

Why configure with Sagas()?

Why is it necessary to configure with Sagas()? I ask because I had been running a saga with raven persistence for the last few months before I noticed the Sagas() is not in the configure.with, in fact I realized I was missing a bit of the RavenPersistence stuff as well. Yet, as far as I know Sagas have been working 98% of the time and persisting to Raven. So I wonder what the Sagas() configuration does differently than not configuring it.
The reason I say 98% of the time is I do notice random messages falling out of a method and not sending the next message it is designated to send in the Saga. I am curious if not having the proper configuration is the cause of this.
_logger.InfoFormat("1.1 - Preparing Saga for; File: {0}", message.FileNumber);
//Creates Saga information
SetupSaga(uploads,
message.Documents,
message.ProcedureID.GetValueOrDefault(0),
file.Client.Id,
message.FileNumber,
message.Stage,
user);
_logger.InfoFormat("1.2 - Upload Saga Unique ID; File: {0}, UniqueID: {1}", message.FileNumber, Data.UniqueID);
Bus.SendLocal(new GetLoanInformation {
UniqueID = Data.UniqueID
});
The NServiceBus Host does a lot of configuration automatically based on roles and profiles. Both the Sagas configuration and the Raven persistence are handled for you automatically. You would only need to do this manually if you were going to run a Saga when self-hosting, which would be somewhat rare.
For a better idea of what happens as a result of all the different roles and profiles, check out All About NServiceBus Host Profiles and Roles. (Disclaimer: This is my blog post.)
The problem you're mentioning is due to something else, but a lot more information would be required to diagnose it.

How to ensure that NHibernate is inside a transaction when saving, updating or deleting?

I'd like to ensure, that when I'm persisting any data to the database, using Fluent NHibernate, the operations are executed inside a transaction. Is there any way of checking that a transaction is active via an interceptor? Or any other eventing mechanism?
More specifically, I'm using the System.Transaction.TransactionScope for transaction management, and just want to stop myself from not using it.
If you had one place in your code that built your session, you could start the transaction there and fix the problem at a stroke.
I haven't tried this, but I think you could create a listener implementing IFlushEventListener. Something like:
public void OnFlush(FlushEvent #event)
{
if (!#event.Session.Transaction.IsActive)
{
throw new Exception("Flushing session without an active transaction!");
}
}
It's not clear to me (and Google didn't help) exactly when OnFlush is called. There also may be an implicit transaction that could set IsActive to true.
If you had been using Spring.Net for your transaction handling, you could use an anonymous inner object to ensure that your DAOs/ServiceLayer Objects are always exposed with a TransactionAdvice around their service methods.
See the spring documentation for an example.
To what end? NHProf will give you warnings if you're not executing inside a transaction. Generally you should be developing with this tool open anyway...