Dynamically setting NServiceBus.TimeToBeReceived at runtime for MSMQ message deletion instead of using [TimeToBeReceived()]

When I put the TimeToBeReceived() attribute on a message, MSMQ deletes the message as expected. From what I’ve read, this attribute uses the “NServiceBus.TimeToBeReceived” header in order to make that happen.

I tried to do the same thing by setting the “NServiceBus.TimeToBeReceived” message header using SendOptions.SetHeader and then sending, but the message was not deleted from the queue.

I’d like to see if it’s possible to assign the time to be received at runtime instead of at design time.

My guess is that the [TimeToBeReceived()] attribute is doing more than just setting the header, or else my test of setting that header from SendOptions would work.

Are there any options that would allow me to set TimeToBeReceived dynamically/at runtime?

Can you provide some more detail about your requirements? Do you need to vary this per message or just make it different in different environments?

My guess is that the [TimeToBeReceived()] attribute is doing more than just setting the header, or else my test of setting that header from SendOptions would work.

You are right. The header is mostly informational. The real work is done under the covers by creating a DiscardIfNotReceivedBefore dispatch property. The relevant behavior is here.

If you cannot use the attribute, we do provide an option to configure this at runtime with a custom convention. If you just want to vary the Time to be Received per endpoint, this may be sufficient.

Here’s the code snippet from the linked docs article:

var conventions = endpointConfiguration.Conventions();
conventions.DefiningTimeToBeReceivedAs(
    type =>
    {
        if (type == typeof(MyMessage))
        {
            return TimeSpan.FromMinutes(1);
        }
        return TimeSpan.MaxValue;
    });

I’d like to be able to apply this “dynamically” per message.

The use case is a scheduler that is polling a db for a list of things that have to be done every 5 minutes. This is a completely unbound dataset, there could be 500 things to do, or 20,000.

A message is dispatched to a handler by the Quartz job and the handler (the “scheduler handler”) reads a list of things to do, updates those things to “in progress” in the db, then decomposes each item in that list into NSB messages and dispatches them.

Another handler (the “processing handler”) is responsible for handling each “thing to do” message and doing the work.

Because of the centralized and polling-specific nature of the implementation, it’s possible that the time between the scheduler handler dispatching the messages and the time it take for the processor handler to work through each message, that the operation is not longer applicable for a given message(s).

I was looking for a way for those messages waiting on the processor handler’s input queue to be discarded by the transport (in this case, unfortunately, MSMSQ) to save the processing handler from having to do the work of looking at the data on the message and then making a decision on whether or not to no-op.