Following the suggested pattern, queue_module:setup_with_options { skip_queue_config_hook = true, ... } plus our own get_queue_config handler that calls queue_helper:resolve_config() and resolve_provider(). kumod --validate then fails with “queue.lua is in use, but it is not the last module to register for the get_queue_config event”. The helper never registered a handler, so my_reg is nil (assets/policy-extras/queue.lua, validate_config, if my_reg ~= #reg). Suggested fix:
if not mod.CONFIGURED.options.skip_queue_config_hook and my_reg ~= #reg then
Our workaround is to keep the helper’s hook and register our handler before it. The handler returns nothing when there is no provider route, so the helper handles the queue.
Related doc mismatch: docs/reference/events/get_queue_config.md says “If a handler returns nil then the next handler will be called”. In crates/config/src/lib.rs the chain only continues when the result is empty (if result.is_empty()). A bare return passes to the next handler, but return nil stops it (“error converting Lua nil to QueueConfig”).
We use the helper for everything except the pool choice: apply() (tenant/campaign headers, X-Schedule, rejecting unknown tenants), resolve_config() with the queue.default → domain → tenant → domain.tenant → campaign merge, overall_max_message_rate, and its pool validation.
Our handler only replaces egress_pool when the tenant has a route for the destination provider. Otherwise it returns nothing and the helper’s own hook handles the queue. Writing a full get_queue_config ourselves would mean reimplementing all of that to change one field.
That’s also why a provider level in the helper itself would be useful, e.g. [provider.'outlook'.'<tenant>'] egress_pool = '...'.
“Related doc mismatch” - nice catch - I keep meaning to document that.
I can open an enhancement ticket for this, but it will be tagged under “requires sponsorship”, mainly because this should also work, though it may be more effort to implement.
local queue_module = require 'policy-extras.queue'
local queue_helper = queue_module:setup_with_options {
skip_queue_config_hook = true,
file_names = {'/opt/kumomta/etc/policy/queues.toml'},
}
kumo.on(
'get_queue_config',
function(domain, tenant, campaign, routing_domain)
if tenant == 'ABCCorp' then
local provider = queue_helper:resolve_config(domain, tenant, campaign)
if provider == "google" then
return kumo.make_queue_config {
egress_pool = 'google_pool'
}
end
end
return
end)