Is it possible to set TTL for Saga without using long timeout where MarkAsComplete is called? - nservicebus

Right now we complete sagas which were successful from business point of view, but we store failed sagas for 3 months - we set a timeout and then mark saga as completed.
Is there a more generic way for setting saga's Time-To-Live which does not involve underlying messaging service?
For example AWS SQS max delay is 15 minutes, but for us it would be enough to run the garbage collection job once a week. Does NSB have this option?

Is there a more generic way for setting saga's Time-To-Live which does not involve underlying messaging service?
NServiceBus implements timeouts using delayed messages. SQS happened to be limited to a maximum of 15 minutes. To overcome this limitation, transport rescheduled the message multiple times to get the desired delay. Other transports such as Azure Service Bus, RabbitMQ, SQL Server transport do not require this as they can send a single delayed message for the necessary time. RabbitMQ doesn't support it natively either, so it also implements the feature internally. There's no "general" implementation. It's always specific to the transport you're using.
That's exactly what NServiceBus is doing by using the delayed delivery. Unfortunately, SQS as you've noticed doesn't support periods longer than 15 mins.
You could use a 3rd party scheduling library that would send a message that would complete the saga. https://docs.particular.net/nservicebus/scheduling/
I'll also follow-up internally to see if there are other recommendations.

Related

NServiceBus Delay Retries configure on only one queue

I have an instance of NServiceBus that is used for multiple queues. Now I have only one queue that requires a special type of delay retries and a custom policy. In this queue I have a 3rd party call, and I want it to be retried 10 times with a specific pattern of time interval.
I have read the documentation about delayed retries, my understanding is that it will affect all the queues, not only the one I want.
How this can be implemented?
I'm using NServiceBus with RabbitMq for testing envs and Azure Service Bus for prod envs.
Recoverability policy is applied on the endpoint level. When you need a certain message type to be processed with a different recoverability policy, you can override the default recoverability policy to customize it to your needs. When you need a completely different number of delayed retries configured that does not match the rest of the messages, you should split the logical endpoint into two and have the message type that requires a different recoverability handled by the new endpoint.

How to specify another timeout queue for NSB?

I am using NSB 4.4.2
I want to have something like heartbeats on my saga to show processing statistics.
When i request a timeout it sends to sagas input queue.
In case of many messages prior to this timeout message, IHandleTimeouts may not be fired at specific time.
Is it a bug? Or how can i use separate queue for timeout messages?
Thanks
You are correct - when a timeout is ready to be dispatched, it is sent to the incoming queue of the endpoint, and if there are already many other messages in there, it will have to wait its turn to be processed.
Another thing you might want to consider, is that the endpoint may be down at that time.
If you want to guarantee that your saga code will be invoked at (or very close to) the time of the timeout, you'll need to set up a high availability deployment first. Then, you should look at setting the SLA required of that endpoint - how quickly messages should be processed, and then monitor the time to breach SLA performance counter.
See here for more information: http://docs.particular.net/nservicebus/monitoring-nservicebus-endpoints
You should be prepared to scale out your endpoint as needed to guarantee enough processing power to keep up with the load coming in.
NOTE: The reason we use the same incoming queue for processing these timeouts is by design. A timeout message is almost always the same priority or lower than the other business messages being processed by a saga. As such, it doesn't make sense to have them cut ahead of other messages in line.
Timeouts are sent to the [endpointname].timeouts

Does NServiceBus 4.x with RabbitMQ support round robing consumers or the competing consumer model?

I'm using NServiceBus 4.x with RabbitMQ 3.2.x as my transport.
I made the assumption that by using RabbitMQ as my transport I would be given the competing consumer model as an option. I understand that NServiceBus employs the "Fannout" exchange type for all exchanges and does not support round robin at this time. However is there a way to configure NServiceBus to take advantage of the levels of indirection via Exchanges and channels that RabbitMQ offers.
I have several consumers I would like to compete for messages from a given queue. What I am observing is subscribers' blocking access to further message retrieval from the queue until the message is consumed. So having more then one consumer at this point does me no good other then redundancy.
After reading some documentation on RabbitMQ I'm assuming that it's normal to block until the Ack receipt is sent from the subscriber. But I had assumed that subscriber #2 would have free access to the queue to fetch another message.
There is mention of increasing the prefetch count on RabbitMQ channel.
Example:
channel.BasicQos(0,prefetchcount,false)
I don't see anywhere that I can change this setting via configuration in NServiceBus. Furthermore as I read what prefetch does I'm really not sure this what i'm looking for.
Is it possible to use RabbitMQ with out a distirbutor type pattern used with MSMQ? Or should I move to MassTransit or Rebus?
Put prefetchcount=2 in your connection string. Any value above 1 will tell the broker to allow more than X unacked message to go out. You need to fiddle with this setting to find the optimum for your scenario.

How can I tell a WAS service polling an MSMQ to wait when busy?

I'm working on a system which amongst other things, runs payroll, a heavy load process. It is likely that soon, there may be so many requests to run payroll at peak times that the batch servers will be overwhelmed.
I'm looking to put together a proof of concept to cope with this by using MSMQ (probably replacing this with a commercial solution like nservicebus later). I using this this example as a basis. I can see how to set up the bindings and stick it together, but I still need a way to tell the subscribers hosted by WAS to only process the 'run heavy payroll process' message if they are not busy. Otherwise the messages on the queue will get picked up straightaway and we have the same problem as before.
Can I set up the subscribing service to say, "I'm busy, I can't take the message, leave it on the queue"? Does the queue need to be transactional?
If you're using WCF then there's no way to conditionally activate the channel thereby leaving the messages on the queue for later.
A better solution is to host the message receiver in a completely different process, for example as a windows service. These can then be enabled/disabled according to your service window requirement.
You also get the additional benefit of being able to very easily scale out the message receivers to handle greater loads (by hosting more instances of your receiver).
One way to do this is to have 2 queues, your polling always checks the high priority queue first, only if there are no items in that queue does it take an item from the other

NServiceBus delay retries

We need to be able to specify a delay in retrying failed messages. NServiceBus retries more or less instantly up to n times (as configured) before moving the message to error queue.
What I need to be able to do is for a given message type specify that its not to be retried for an arbitrary period of time
I've read the post here:
NServiceBus Retry Delay
but this doesn't give what I'm looking for.
Kind regards
Ben
This isn't supported as of right now. What you can do is let the messages go to the error queue and setup and endpoint to monitor that queue. Your code could then determine the rules for replaying messages. You could use a Saga to achieve this in combination with the Timeout manager.
Typically you'll have some rules around when to replay messages. In NSB 3.0 we have a better way to do this using the FaultManager. This gives you options on where to put failed messages and includes the exception. One of the options is a DB which you could then set up a job to inspect the exception and determine what to do with it.
Lastly a low tech way of getting this is to schedule a job that runs the ReturnToSourceQueue tool periodically to "clean up". We are doing this and including an alert so we don't endlessly cycle messages around.