Messages sent through the Particular Service Platform can be configured with a Time-To-Be-Received (TTBR) value. TTBR instructs the platform to automatically discard a message if it is not processed within a specified period, freeing up system resources and preventing outdated messages from being handled.
Benefits of using TTBR:
- Reduces processing of stale or irrelevant messages.
- Frees up resources in high-volume environments.
- Ensures only timely, valuable messages are processed.
TTBR applies only to messages that have not been handled. A message is considered handled if it has been successfully processed, moved to the error queue, or audited. The TTBR value is removed from handled messages to prevent message loss. You can inspect the original TTBR value in the NServiceBus.
header.
If a message has no value after a certain period, specify a TTBR to allow it to be discarded.
How to Set Time-To-Be-Received
You can specify a TTBR interval for a message in the following ways:
Using an Attribute
Apply an attribute to the message class to set TTBR:
// Discard after one minute
[TimeToBeReceived("00:01:00")]
public class MyMessage
{
}
Using a Custom Convention
Define a custom convention in code to set TTBR for specific messages:
var conventions = endpointConfiguration.Conventions();
conventions.DefiningTimeToBeReceivedAs(
type =>
{
if (type == typeof(MyMessage))
{
return TimeSpan.FromMinutes(1);
}
return TimeSpan.MaxValue;
});
Clock synchronization considerations
When using TTBR, be aware of potential clock synchronization issues between sender and receiver. If the receiver's clock is ahead of the sender's, messages may be discarded immediately as stale.
- This issue is most relevant for small TTBR values.
- In most environments, clocks are only a few minutes out of sync.
Recommendation: Add the maximum expected clock drift to the TTBR value. For example, if TTBR is 90 seconds and the maximum clock drift is 300 seconds, set TTBR to 390 seconds.
Discarding messages at startup
In certain situations, it may be required that messages in the incoming queue should not be processed after restarting the endpoint. This usually applies to development and test environments, but may also be appropriate for messages containing information that gets outdated or otherwise unneeded, e.g. change notifications, readings from sensors in IoT apps, etc.
It's not recommended to discard messages at startup in a production environment because it may lead to subtle message loss situations that can be hard to diagnose.
To discard all existing messages in the incoming queue at startup:
endpointConfiguration.PurgeOnStartup(true);
Caveats
TimeToBeReceived relies on the transport infrastructure to discard expired messages. As a result runtime behavior is highly affected by the implementation in the different transports.
MSMQ transport
MSMQ continuously checks the TimeToBeReceived of all queued messages. As soon as the message has expired, it is removed from the queue, and disk space gets reclaimed.
MSMQ enforces a single TimeToBeReceived value for all messages in a transaction. To prevent message loss, TimeToBeReceived
is not supported for endpoints with transaction mode SendsAtomicWithReceive
or TransactionScope
by default.
Due to a bug in Version 6 TransportTransactionMode.
wrongly enlisted all outgoing messages in the same transaction causing the issues described above.
For more details about how the MSMQ transport handles TimeToBeReceived, see discarding expired messages in MSMQ.
RabbitMQ transport
RabbitMQ continuously checks the TimeToBeReceived, but only for the first message in each queue. Expired messages are not removed from the queue, and their disk space is not reclaimed until they reach the front of the queue. Using TimeToBeReceived as a disk-saving measure on RabbitMQ is recommended only when all messages in the queue use the same TimeToBeReceived value. Otherwise, messages in front of the queue may prevent other, stale messages from being cleaned.
Azure transports
The Azure transports evaluate the TimeToBeReceived for a message only when the message is requested by the client. Expired messages are not removed from the queue and their disk space will not be reclaimed until they reach the front of the queue and a consumer tries to read them. Using TimeToBeReceived as a storage saving measure on the Azure transports is not a good choice for queues with long-lived messages like audit and forward.
SQL transport
The SQL Server transport runs a periodic task that removes expired messages from the queue. The task is first executed when the endpoint starts and is subsequently scheduled to execute 5 minutes after the previous run when the task has been completed. Expired messages are not received from the queue and their disk space will be reclaimed when the periodic task executes.