2
votes

i have a azure worker role with an nservicebus host 4.7.5 . This host sends events on azure servicebus transport and to a topic. Is there a way to either delay the sending of the event or setting some properties to make sure that the message appears after a delay on the topic subscription? The host sends out events after it notices a change in the primary database. There are several secondary databases into which the primary data write is replicated. The receivers are also azure worker roles that use nservicebus host and have subscription to the topics.

By the time the receivers receive the message, due to replication lag the secondaries may have out of sync data.

one option is to use primary database to read but that is a route which i dont want to take.

1

1 Answers

3
votes

Would it be possible to fail-early in your subscription endpoints and let the retries take care of it? You can fine-tune the retry times/delays to make sure your secondary databases are updated before the message is retried.

You still need to find the best way to lookup your data from the database and a way to differentiate between the version in the event. You could use version numbers or last update dates in case of updates, or just lookup by an identifier in case of creation.

The endpoint reading data off the secondary database might have a event handler like this:

public class CustomerCreationHandler : IHandlesMessage<CustomerCreated> 
{
    public void Handle(CustomerCreated @event) 
    { 
        var customer = Database.Load(@event.CustomerId);
        if(customer == null) 
        { 
            throw new CustomerNotFoundException("Customer was not found.");
        }

        //Your business logic goes here
    }
}

You can control how many times the event handler will retry and how much delay there'll be between each attempt. In this case, the message will be retried by First-Level retries and then handed over to Second-Level retries which is configured below.

class ProvideConfiguration :
    IProvideConfiguration<SecondLevelRetriesConfig>
{
    public SecondLevelRetriesConfig GetConfiguration()
    {
        return new SecondLevelRetriesConfig
        {
            Enabled = true,
            NumberOfRetries = 2,
            TimeIncrease = TimeSpan.FromSeconds(10)
        };
    }
}

Alternatively, instead of just publishing the event, you can send a deferred message to the same endpoint to then publish the actual event after certain amount of time is passed.