Files
kumomta/docs/reference/events/requeue_message.md
T
Wez Furlong d063c96b5f yell loudly when sig.register() should have been called
A number of our lua event handlers allow registering multiple
implementations to facilitate modular use.

For that to work, we must know ahead of the user lua call running
that any given handle is allowed to register multiple times.  This is so
that we can report a meaningful error when incorrectly using a singleton
handler multiple times, and so that we can record a list of handlers
for the multiple case.

Prior to this commit, if we forgot to arrange to register the signature
as part of the context setup the consequence was that the event handler
would get registered as a singleton and when we went to call it, because
the signature is marked as allowing multiple but was not registered
as multiple, we would skate through and do nothing without reporting
an error because we assumed that the signature was registered
consistently.

In hindsight, that's a terrible idea because it results in silently
ignoring the registration issue, and not calling the event handler
at all.

This commit consolidates the multiple/single value resolution into
the same flow, then adds a check to confirm that we have a list
of handlers registered for the allow_multiple case, raising an
error otherwise that will hopefully encourage users to report
this problem to us if it manifests again in the future.

This commit includes fixing two event handlers that we missing
their signature registration.

One of them was broken anyway by being registered with a name
that didn't match the docs.

refs: https://github.com/KumoCorp/kumomta/issues/236
2024-10-07 10:25:47 -07:00

77 lines
3.0 KiB
Markdown

# `kumo.on('requeue_message', function(message, smtp_response))`
{{since('dev')}}
!!! note
This event was actually added in `2024.06.10-84e84b89` but under
the erroneous name `message_requeued`, and with a broken event
registration that prevented it from working. That was corrected
in the version shown above when the `smtp_response` parameter was added.
This event is triggered when a message encountered a transient failure.
Its purpose is to allow you to re-bind the message to an alternative
queue, perhaps to relay it via an alternate tier or to use an alternative
pool for egress.
The `smtp_response` parameter is a one-line rendition of the SMTP
response that resulted in the message being requeued. There are a couple
of internal triggers for a requeue that are not directly caused by
an SMTP response. Those responses have `KumoMTA internal:` prefixed
the to textual portion of the response.
Multiple instances of the `requeue_message` event can be registered,
and they will be called in the order in which they were registered,
until all registered events are called, or until one explicitly
returns `nil` to signal that no more should be triggered.
The event is triggered prior to incrementing the number of attempts,
so `message:num_attempts()` will return one less than the current
number.
In order to re-bind the message you will typically alter one or more of the
meta values of the message that impact the queue name:
* `queue`
* `routing_domain`
* `tenant`
* `campaign`
See [Queues](../queues.md) for more information.
If the effective queue name for the message is changed as a result of
dispatching the `requeue_message` event, then the message will be immediately
eligible for delivery in the context of its new queue, however, if the message
has scheduling constraints set via
[msg:set_scheduling](../message/set_scheduling.md) those will remain in effect
unless you explicitly clear them. The reason for this is that kumod doesn't
have any implicit knowledge of the semantics of the queue, so it doesn't know
whether the scheduling constraints should remain in force or not.
In the example below, a message is re-routed to a smart host after
the third attempt to send it encounters a transient failure.
```lua
local SMART_HOST = '[10.0.0.1]'
kumo.on('requeue_message', function(msg)
local queue = msg:get_queue_name()
if queue ~= SMART_HOST and msg:num_attempts() >= 2 then
-- Re-route to alternative infra to manage the rest of the send
msg:set_meta('queue', SMART_HOST)
-- clear any scheduling constraints, as they do not apply
-- when sending via a smart host
msg:set_scheduling(nil)
end
end)
```
Calling [kumo.reject](../kumo/reject.md) to raise an error in your event
handler (regardless of the code parameter passed to `kumo.reject`) will
cause the message to bounced; a `Bounce` record will be logged and the
message will be removed from the spool.
Any other kind of error raised by the event handler will cause the error
to be logged to the diagnostic log, and the message returned to its
original scheduled queue.