Delaying Messages

Delaying message delivery for scheduled processing

You publish OrderWasPlaced. Two handlers subscribe: chargeCard (must run now) and sendReminder (run in 24 hours if the card hasn't been charged). With a single delay on the message, both fire together. Ecotone delays per handler, not per message — so one subscriber can run immediately while another waits 24 hours.

circle-info

Asynchronous Message Channel need to support delays, in order to make use of this feature.

Message Handler Delay

You may delay handling given asynchronous message by adding #[Delayed] attribute.

#[Delayed(new TimeSpan(seconds: 50))]
#[Asynchronous("notifications")]
#[EventHandler(endpointId: "welcomeEmail")]
public function sendWelcomeNotificationlWhen(UserWasRegistered $event): void
{
   // handle welcome notification
}

Using Expression language

To dynamically calculate expected delay, we can use expression language.

#[Delayed(expression: 'payload.dueDate']
#[Asynchronous("orders")]
#[EventHandler(endpointId: "cancelOrder")]
public function cancelOrderIfExpired(OrderWasPlaced $event): void
{
   // it will trigger at payload.dueDate, which is \DateTime object
}
circle-check

We could also access any object from our Dependency Container, in order to calculate the delay and pass there our Command:

Message Delay

We may send an Message and tell Ecotone to delay it using deliveryDelay Message Header:

circle-check

Delaying using exact Date

We may also delay to given date time:

Controlling Header Override Behavior

By default, the #[Delayed] attribute will override any existing deliveryDelay header that was set when sending the message. However, you can change this behavior using the shouldReplaceExistingHeader parameter.

Using Attribute as Default (Not Override)

When you want the attribute to act as a default value that can be overridden by message metadata:

With shouldReplaceExistingHeader: false:

  • If the message already has a deliveryDelay header, the attribute will not override it

  • If the message does not have a deliveryDelay header, the attribute value will be used

This is useful when you want:

  • Handler-level defaults via attributes

  • Per-message overrides via metadata (e.g., dynamic delays based on business logic)

Last updated

Was this helpful?