Skip to content
Mogens Heller Grabe edited this page Apr 8, 2019 · 5 revisions

All Rebus endpoints have a built-in capability to handle "deferred messages", i.e. messages supplied with a couple of special headers. These headers are automatically assigned by Rebus when you

await bus.Defer(TimeSpan.FromMinutes(2), yourMessage);

so you will most likely not have to mess around with them yourself. These are the headers that will be added to the message:

  • rbs2-deferred-until - ISO8601-encoded timestamp of when the message is meant to be consumed
  • rbs2-defer-recipient - queue address of the endpoint that is meant to consume the message

When Rebus receives an incoming message with these headers, and it determines that the message is not meant to be consumed yet, it will either a) store the message in its timeout storage, or b) forward the message to a known timeout manager (if you have configured that particular endpoint to use an external timeout manager).

If it determines that the message can be consumed already, it will immediately forward the message to the intended recipient.

Default timeout manager

By default, Rebus will throw an exception if you try to Defer/DeferLocal a message without having configured a timeout manager. This is because it could be an error if you did it, and if it e.g. would just use the in-mem timeout manager as the default, then the message could get lost in the event of a restart.

Internal timeout manager

You can configure a timeout manager by going

Configure.With(...)
    .(...)
    .Timeouts(t => t.StoreIn(...))
    .(...)

for example

const string localDb = "server=.; database=rebus; trusted_connection=true";

Configure.With(...)
    .(...)
    .Timeouts(t => t.StoreInSqlServer(localDb, "RebusTimeouts"))
    .(...)

in order to store the timeouts in a table called RebusTimeouts in a local SQL Server.

If your deferred messages are not that important and you can tolerate losing them when your endpoint restarts, you can enable the in-mem timeout manager like this:

Configure.With(...)
    .(...)
    .Timeouts(t => t.StoreInMemory())
    .(...)

External timeout manager

Sometimes it can be desirable to assign the timeout manager responsibility to only a few endpoints, and then configure other endpoints to use an external timeout manager, like so:

Configure.With(...)
    .(...)
    .Options(t => t.UseExternalTimeoutManager("timeoutmanager"))
    .(...)

which will then send deferred messages to the timeoutmanager address.

Clone this wiki locally