Commit Graph
23 Commits
Author SHA1 Message Date
Wez Furlong 6479810368 queue helper: add invalidate_with_epoch option to queue_helper_data cache 2026-04-02 08:55:13 +01:00
Wez Furlong 332595ee2a queue.lua: add typing to setup methods
We had an issue where a typo resulted in a relatively inscrutable
error at runtime:

```lua
local queue_helper =  queue_module:setup ('/opt/kumomta/etc/policy/queues.toml')
```

produced this:

```
problem initializing: call validate_config callback: runtime error: /opt/kumomta/share/policy-extras/queue.lua:602: bad argument #1 to 'for iterator' (table expected, got nil)
stack traceback:
        [C]: in function 'next'
        /opt/kumomta/share/policy-extras/queue.lua:602: in function </opt/kumomta/share/policy-extras/queue.lua:551>
Error: Initialization raised an error: call validate_config callback: runtime error: /opt/kumomta/share/policy-extras/queue.lua:602: bad argument #1 to 'for iterator' (table expected, got nil)
stack traceback:
        [C]: in function 'next'
        /opt/kumomta/share/policy-extras/queue.lua:602: in function </opt/kumomta/share/policy-extras/queue.lua:551>
```

with the changes in this commit we'll present this issue like this,
during server startup, which points a little more clearly at the setup
call and the file names parameter, and suggests more strongly that it
should be a list of strings (or config objects):

```
    runtime error: [string "./simple_policy.lua"]:52: assets/policy-extras/queue.lua:463 QueueHelperSetup: invalid value for field 'file_names'
    assets/policy-extras/queue.lua:463 Expected value of type 'list<variant<string,QueueHelperConfig>>' but got type 'string' '/opt/kumomta/etc/policy/queues.toml'
    stack traceback:
        [C]: in function 'error'
        assets/policy-extras/typing.lua:78: in method 'raise'
        assets/policy-extras/typing.lua:249: in metamethod 'newindex'
        assets/policy-extras/typing.lua:258: in function <assets/policy-extras/typing.lua:253>
        (...tail calls...)
        assets/policy-extras/queue.lua:463: in function 'policy-extras.queue.setup_with_options'
        (...tail calls...)
        [string "./simple_policy.lua"]:52: in main chunk
```

this change actually surfaced a minor issue in the ndr.lua file that is
part of an integration test, as well as in my adhoc simple_policy file.
2026-03-04 09:23:08 +00:00
Wez Furlong db5ebb88a7 message: expose recipient list to lua api
message:recipient() may now return an array style table
holding the recipient list, if there is more than a single
recipient on the message.

Since this can be somewhat ambiguous/frustrating to work with,
there is now also a message:recipient_list() that will always
return an array style table, even if it holds just a single
element.

The included helpers have been updated to use `message:recipient_list`.

message:set_recipient() will now optionally accept an array
style table holding the recipient list to be set.
2025-10-07 07:52:58 +01:00
Mike Hillyer 58e9770206 We miss you Mister Rogers. 2025-07-18 12:11:14 -04:00
Wez Furlong 3071fe9701 add shrink_policy queue config option
This allows reducing how much of a message is freed when it is
delayed.
2025-02-21 17:15:52 -07:00
Wez Furlong 0ab606cfee memoize: make epoch-based invalidation optional
It is not always desirable to invalidate with the epoch,
so allow opting in instead of always invalidating that way.
2025-02-06 11:06:25 -07:00
Wez Furlong fefb6dfe0a fixup queue helper issue hidden by register issue
we hadn't encountered this until now because the issue
resolved in d063c96b5f meant
that this logic wasn't triggered.
2024-10-07 12:18:05 -07:00
Wez Furlong fadfd6d9d2 queue.lua: add cache for provider name resolution
When using a healthy dose of tenant+campaign, we can have a large
number of requests for the same provider, so caching is desirable.
2024-09-13 09:37:01 -07:00
Wez Furlong 64fac57d09 formalize provider information for queues, add to logs
The recent changes to enable shaping based on a pattern-matched provider
are nice, but it is important to be able to observe their effects.

So far this has been awkward because the provider concept was purely a
function of the logic in the shaping.lua file and nothing else.

This commit introduces the concept of a `provider_name` field in
both the EgressPathConfig and QueueConfig structs.

The idea is that the `get_egress_path_config` and `get_queue_config`
events are free to populate this field as makes sense to them, so that
the core is then aware of which provider is associated with those
queues.

Once we have that data, we're then able to log it as a field in the
JsonLogRecord.

That is what this commit does. There are some interesting points to note
about the implementation here:

1. shaping.lua will implicitly assign provider_name if it matches
   any providers.

2. It is technically possible for a shaping.toml to define multiple
   providers that match a given domain. In that circumstance, the
   last matching provider is the winner when it comes to assigning
   the provider_name field.

3. In order to populate the provider_name in the queue.lua helper,
   we need to be able to call out to the get_egress_path_config
   event handlers, so a new kumo.invoke_get_egress_path_config
   has been added to support that.

4. kumo.invoke_get_egress_path_config isn't 100% done: there are
   a couple of fields (openssl related) that don't have a defined
   serializer, so we're simply omitting them.  The function is
   "done enough" for the purposes of retrieving the provider_name

refs: https://github.com/KumoCorp/kumomta/issues/276
2024-09-12 20:51:00 -07:00
Wez Furlong f7e68070d1 config: introduce ConfigEpoch and policy file monitoring
This commit adds a background task that periodically evaluates
a glob expression that defaults to the recommended configuration
location and filename suffixes, and a set of additional paths
to observe.

Whenever the hash of that combined set of files changes it causes the
ConfigEpoch to increment and broadcast to subscribers that the
configuration has changed in some fashion.

The QueueConfig struct has a new refresh_strategy which can select
between the earlier Ttl based refresh for the queue config, or
the new Epoch refresh.

When the epoch changes, the config refresh task will cause each of
the scheduled queues that is using the Epoch strategy to re-evaluate
the get_queue_config event to update their configuration.

The queues helper sets the refresh strategy to Epoch.

A new HTTP endpoint has been added: it can force a bump in the
current epoch, effectively causing all epoch subscribers to
wake up and perform a refresh.

These changes avoid doing O(number-of-scheduled-queues) get_queue_config
callouts every refresh_interval; instead, the work is performed only
when an appropriate change is detected or triggered.
2024-09-02 10:42:14 -07:00
Wez Furlong 426b5b8d31 log_hooks: add typing
This will perform more explicit checks to make sure that the name
is defined and so on. It also now will check for conflicting
log hook names as well.

refs: #211
2024-06-28 12:31:49 -07:00
Wez Furlong e96dfcfe38 typing: refine error handling for _dynamic fields
Better distinguish between unknown and mismatched types for dynamic
fields, and show a better error message for them.

refs: #211
2024-06-28 10:06:27 -07:00
Wez Furlong 11bbd07f3f listener_domains: add typing and validation
refs: #211
2024-06-28 09:43:38 -07:00
Wez Furlong f0b91dd652 queue.lua: add typing
I regret optimizing the structure for toml when this module was
created, as it makes it difficult to define a regular schema.

This commit introduces typed records for the queue helper
data structure, and, unfortunately, a parsing layer to adapt
between the toml data and the well-defined types.

It also adjusts how lua tests are run; previously we'd co-opt the main
flow of parsing by looking at an env var, but since the modules can now
potentially require each other (especially the typing module) we need to
de-couple from that, otherwise what happens is that we'd only ever run
the typing module tests and exit. So we now have a script that imports
all the modules and runs their respective `:test()` methods.

refs: #211
2024-06-28 08:54:46 -07:00
Wez Furlong fb2dad8b10 validation: check for ordering of get_queue_config events
refs: https://github.com/KumoCorp/kumomta/issues/211
2024-06-27 06:54:55 -07:00
Wez Furlong 3139be2cfd Add new kumod --validate flag
The purpose is to provide a deeper, offline validation pass
of the policy configuration, prior to deploying and making it
live.

The system behavior changes when in `--validate` mode:

* Listeners, spool and spawned tasks will be silently skipped;
  the parameters will be validated but the primary functions
  of those things will be skipped silently.
* After triggering the `init` event, an additional new `validate_config`
  event (which can be registered multiple times) will be triggered
  to allow lua modules to perform extended validation.
* A module can either raise an error via `error` to immediately report
  a problem, or instead call a new, preferred, `kumo.validation_failed()`
  function to flag validation as failed but allow additional validation
  to be performed and summarized all together.
* Once the `validate_config` event returns, the process will terminate
  with either exit code 0 for a successful validation, or non-zero
  to indicate that something failed.

Validation errors are reported in a human readable form.

This commit adds validate_config event handlers for the following
helper modules:

* `shaping` - any warnings reported by the underlying rust code
  will be reported here and cause validation to fail. This is
  functionally equivalent to using the `validate-shaping` binary,
  except that it will automatically be passed the set of shaping
  files defined by your `init.lua`

  If the `sources` helper is also configured, the list of sources
  referenced by the shaping config will be cross-checked against
  the sources data to confirm that all possible sources are defined.

* `sources` - each listed source and pool will be validated by
  calling `kumo.make_egress_source` or `kumo.make_egress_pool`
  respectively.

  Pool membership will be validated to confirm that every
  listed pool is defined in the sources data.

* `queues` - each domain and tenant that references an egress_pool
  will be cross-checked with the `sources` helper, if the sources
  helper has been configured.

It is now an error to attempt to setup any of the above helpers
more than once.

refs: https://github.com/KumoCorp/kumomta/issues/211
2024-06-25 11:05:04 -07:00
Wez Furlong f83b838a37 queue helper: add routing_domain option
This commit allows:

```toml
[queue.'my.own.hostname']
routing_domain = '[10.0.0.1]'
```

The effect of this is that, if the recipient domain matches a `queue`
block with a `routing_domain`, the value of that entry will be assigned
as the `routing_domain` meta field of the message.

The intent is for this to be used when DNS routes mail to the current
instance, but for when it is desirable to relay the mail onto some
location that is not visible in DNS.

refs: https://github.com/KumoCorp/kumomta/issues/141
2024-03-21 14:24:14 -07:00
Wez Furlong 8ef3af530a add overall_max_message_rate option to queue helper
The intent is to limit the overall rate at which a tenant
is able to send messages out from the server. It is NOT related
to the rate at which messages can be injected to ths server.

This is allowed in two locations:

* Directly in the tenant block
* In a new campaigns table located under a tenant

```toml
[tenant.'mytenant']
egress_pool = 'tpool'
overall_max_message_rate = "100/s"

[tenant.'mytenant'.campaigns.'mycampaign']
overall_max_message_rate = "50/s"
```

The tenant level throttle is checked first, and if it permits
the message, then the campaign specific throttle is checked.

refs: https://github.com/KumoCorp/kumomta/issues/143
2024-03-21 09:16:40 -07:00
aryeh 03a43460c6 Update queue.lua to allow protocol field in queues.toml (#155)
* Update queue.lua to allow protocol field in queues.toml

resolve_config skips all table fields in the queues.toml config subsection, so  adding a protocol field in any of the sections other than [queue.default] gets ignored.

Added an exception in the queue.lua:resolve_config so "protocol" setting fields are not ignored in the the queues.toml  subsections.

* Refactor to use a helper function

Add helper function to determine if a value in the queues.toml objects is a main queue_config option and should therefore be copied/merged into the queue_config options.
2024-03-20 08:16:50 -07:00
02504a06d5 queue helper: allow skipping get_queue_config hook (#101)
Adds expanded constructor method that allows bypassing the hook.
Exposes the config resolver method on the returned queue helper object.

Co-authored-by: ncai <ncai@chapsvision.com>
Co-authored-by: Wez Furlong <wez@wezfurlong.org>
2023-11-30 10:34:32 -07:00
Wez Furlong 0ffbcf7ed0 queue.lua: fix typo 2023-11-06 11:03:06 -07:00
Wez Furlong 68b7979783 queue.lua: allow removing tenant and/or campaign header 2023-11-06 10:59:49 -07:00
Wez Furlong e9838cd1a9 new: queue helper
This helps to configure tenant and campaign assignment and scheduled
queue configuration.

refs: https://github.com/KumoCorp/kumomta/issues/90
2023-11-03 13:44:13 -07:00