Commit Graph
3087 Commits
Author SHA1 Message Date
Wez Furlong af2e930b3f tsa: improve sizing diagnostics
Make things a bit more compact while still informative when
displaying the size of the different parts of the state on
both startup and shutdown.

Similarly, show when we prune records on startup.
2025-04-14 11:58:56 -07:00
Wez Furlong 6bc216c18d docs: make tsa changelog entry very slightly more broad
Aside from importing data on startup, we no longer use sqlite.
2025-04-14 11:38:24 -07:00
Wez Furlong 1f37a104f6 mailparsing: rebuild of binary attachments could corrupt them
We were blanket-applying the text charset conversion and it was
interpreting the binary bytes as windows-1252 content, which could cause
us to then re-encode the content as the utf8 equivalent of the 1252
interpretation of those bytes.
2025-04-14 10:05:27 -07:00
Wez Furlong b8e77e594d tsa: migrate suspensions from sqlite to tsa state 2025-04-14 09:46:17 -07:00
Wez Furlong cfc00c5837 tsa: migrate bounces from sqlite to tsa_state 2025-04-11 14:23:58 -07:00
Wez Furlong 344ee0ee1d tsa: migrate config overrides from sqlite to new state
This moves another set of data from the sqlite db and into our
own data structures.

The sqlite data will be copied into the new structure on startup
if we haven't already populated that data.
2025-04-11 13:36:34 -07:00
Wez Furlong c8de19a1ba tsa: remove stray debug 2025-04-11 10:25:46 -07:00
Wez Furlong 8c3b297cda tsa: improve event_history storage
In a pathological configuration (essentially unbounded and continually
increasing number of campaigns, tenants, coupled with a synthetic
10% rate of triggering drastic bounce automation rules) I observed
that tsa could trip over itself when locking the sqlite db to
maintain the event history table.  This in turn causes delays
in responding to the shaping data endpoint, leading to timeout
errors in kumod.

This commit removes the sqlite-based event_history table that was
the source of that contention and replaces it with a much more
compact and easier to reason about set of in-memory data structures
built around a sharded hash map.  This makes it very quick to
insert and return the current count when assessing rules with
triggering thresholds.

This new state is serialized using msgpack and periodically saved
in the background, as well as on shutdown.
2025-04-11 10:04:31 -07:00
Wez Furlong 7c3e3e40be lruttl: refine semaphore timeout message
include the timeout duration and describe what it means a little better
2025-04-10 14:33:49 -07:00
Wez Furlong dd57bcfabe kumod: add kumo-api-types to default log filter
This is mostly to aid in my debugging efforts
2025-04-10 14:30:56 -07:00
Wez Furlong 06fa510510 kumo.spawn_task: move away from LocalSet
This is lingering from the past; we don't need LocalSet any
more. I thought this might be causing some scheduling issues,
but it was neutral overall, so this commit is really just
a code cleanup.
2025-04-10 14:29:49 -07:00
Wez Furlong 5080fdbca5 tsa: improve error messaging around sqlite busy result
Show when things are taking a while, and clarify the
timeout value that was hit when/if we experience
SQLITE_BUSY.
2025-04-10 12:24:14 -07:00
Wez Furlong 76e73084f8 tsa: minor refactor: better encapsulate database 2025-04-10 12:04:41 -07:00
Wez Furlong f8ccda9dfc admin bounce: add caching+negative caching for queue insertion
For sites with large numbers of admin bounce entries, it is
desirable to negatively cache the lookup so that we can avoid
extraneous matching overhead.

We use a generation counter to determine if any rules have changed
and allow that to drive the invalidation of negative caching.

Otherwise, we cache the last lookup and, if the generation is the
same, then we cache the prior result and respect its expiration.
2025-04-10 10:37:57 -07:00
Wez Furlong 81b840b317 cargo update 2025-04-10 08:44:39 -07:00
Wez Furlong 8ecbe25b4e set_timeq_spawn_reinsertion is now the default
After running this at a couple of sites, this appears to be
good overall, so let's remove the option, reduce complexity
and make things better by default.
2025-04-10 08:42:18 -07:00
Wez Furlong 95ed7cfdc3 singleton wheel: shift admin bounce detection to insert_ready
I noticed on a busy system with over 1500 active admin bounce
entries (created via automation) that cpu was quite busy in qmaint.

I believe that is because we were potentially spawning a new
async qmaint task for every message moving from the wheel and into
the ready queue.

This commit removes that logic, and replaces it with a per-message
check in insert_ready.
2025-04-10 08:32:54 -07:00
Wez Furlong cc2383af80 log hooks: release backlog sema prior to insertion
Queue insertion can generate log records if queues are full,
so holding a backlog permit could lead to blocking-like
behavior when the system is relatively saturated.

Let's release the permit prior to insertion; that way
it still provides some benefit (limiting the should-enq hook
calls) while not getting in the way.
2025-04-09 10:46:22 -07:00
Wez Furlong 4307849e5b lruttl: simplify with more defer!
Replace my manual Drop helper with a defer! block
2025-04-09 10:46:15 -07:00
Wez Furlong e26ac46535 add some clippy rules for dashmap
They didn't catch anything, but we have them in place for the
future.
2025-04-09 10:26:12 -07:00
Wez Furlong 4b7577ebbd even more clippy 2025-04-09 10:26:12 -07:00
Wez Furlong a1f4172f4f more clippy 2025-04-09 10:26:12 -07:00
Wez Furlong dc265804d3 summarize-memory: clippy suggestion 2025-04-09 10:26:11 -07:00
Wez Furlong e3fdcaa628 cargo clippy --fix 2025-04-09 10:26:07 -07:00
Wez Furlong d6a376f2f3 cargo update 2025-04-08 12:44:54 -07:00
Wez Furlong 89d1398b17 lruttl: improve cancellation safety
The pattern used in the logic was that in the Pending case,
once we had acquired the semaphore, we'd do some prep work,
then await the completion of the populator function, then
store the result and then close the semaphore to force all
wakers to kick out and consult the return value.

The await is a cancellation point, which means that if the
call stack above the population function encounters a timeout
(eg: data_processing_timeout) then the whole state is dropped
and never consulted again.

The drop would release the semaphore permit and allow another
actor to acquire it, which is partially OK, but we really do
want to close the semaphore to wake up everyone in that case.

This commit switches from the explicit close at the end of
the scope to using defer! to handle it in all exits from
that particular scope, including the drop on cancellation.

Doing that highlighted a busy loop in response to the cancellation; to
deal with that, while we have the entry locked, if the semaphore is
already closed we'll treat it the same way as an expired ttl and allow
kicking off a new resolve.
2025-04-08 12:44:41 -07:00
Wez Furlong 1cc4027acf egress_source: add negative caching for queue names
This is a micro optimization, but it helps to take a little
bit off pressure during queue name resolution if the domain
isn't resolving.
2025-04-08 12:44:41 -07:00
Mike Hillyer b034b1b9df Update bounces.toml
Adding a couple of missed codes.
2025-04-07 22:21:22 -04:00
Wez Furlong 0f6491b6b1 ci: amazon: pull the base amazon image
The issue was that there was a major update to libstdc++; that's
visible in our builder image, but our CI system had the older one
cached.

Probably.
2025-04-07 07:12:36 -07:00
Wez Furlong f741fa786a ci: speculative fix for amazonlinux2023 build issue
yum doesn't think that anything has libstdc++, it's probably
a metadata issue in that image.
2025-04-07 06:46:56 -07:00
Wez Furlong 95654c61fd shaping.lua: increase shaping_data cache capacity
I've observed a system where we had more than 4 outstanding
shaping_data lookups from different ConfigEpochs; that system
had slow dns resolution and we ended up looping for these because
the capacity was not high enough and the population of the result
always took too long.

Let's just give ourselves a bit more headroom; this coupled
with the earlier commits that adjust retry behavior should
help to smooth things out in this situation.
2025-04-06 09:55:02 -07:00
Wez Furlong d5e3d6a82a lruttl/memoize: adjust retry behavior
It's not a good idea to automatically retry internally at the lruttl
layer, as there is no bound on the retries and not enough context in the
cache layer to decide if we really should retry.

This commit removes the `retry_on_sema_timeout` flag from lruttl
and replaces the implementation of the mod-memoize
retry_on_populate_timeout flag with a simple 3 attempt retry
loop in the failure case.

Importantly, those retries in mod-memoize have the opportunity
to adjust to a bumped ConfigEpoch, which is important for the
pathological situation where a flood of changes stream in from
TSA daemon and there is a delay in handling populate, and the
cache capacity is not sufficient to accommodate that run
of epoch bumps.
2025-04-06 09:49:19 -07:00
Wez Furlong 8b1b639d98 message: implicitly load data/meta when calling lua get/set meta/data
I saw an instance where the throttle_insert_ready_queue event was
trying to inspect the metadata but failing because the metadata was
not loaded.

This should avoid that problem.
2025-04-06 08:59:44 -07:00
Wez Furlong eda083f083 dns-resolver: use thundering herd protection and add semaphore
This commit does two things:

* Migrate the limit of 128 concurrent lookups from the shaping code
  and into the general mx lookup code
* Adjust the mx lookup implementation to run inside the cache
  getter, which applies thundering herd protection to the lookup.

These together will constrain the amount of queries being sent
to the upstream dns resolver and reduce the chances of it being
overwhelmed, especially if we are doing duplicate queries from
multiple concurrent contexts simultaneously.
2025-04-06 08:45:49 -07:00
Wez Furlong 5eb57e63d5 shaping.toml: disable dane for office365-dane
We cannot default it to enabled because a fully working
dane setup requires additional configuration in the resolver
and we cannot guarantee that that has happened here.
2025-04-06 07:47:00 -07:00
Wez Furlong f940ce6b72 Show version info on service startup
It's a little awkward to reason about whether you're running the latest
build or not after an upgrade, so let's explicitly print the version
to the journal.

For posterity, regardless of whether you have this particular commit or
not, you can determine the running/online version by looking at the
openapi schema document:

curl -s 'http://127.0.0.1:8000/api-docs/openapi.json' | jq .info.version
2025-04-05 07:02:22 -07:00
Wez Furlong 2b1146aa91 queue: avoid potential "singleton_wheel: reinsert_ready: metadata must be loaded first"
There is a potential race between the timerwheel tick and bulk queue
operations (flushing, bouncing).  The logic in the tick case has
some accommodations for this, but there is another outstanding
that can result in racing to manage the metadata load state
on a message.

In the tick case, we load it if needed, then resolve the queue
name, so that we can resolve the Queue handle.

We need the queue handle to decide whether we are responsible
for the message, or whether we might be racing with a concurrent
action.

In the race case, the other actor may have decided to release
the message metadata, which will cause the queue name resolution
to fail.

While we could just shrug and silently ignore the error in that
case, that makes me uneasy.

What this commit does is adjust the v1 wheel entry so that we
capture weak references to both the message and its containing
queue.

Then when we tick, we can simply upgrade both of those and
reconcile without needing to manipulate any message metadata.

These changes unfortunately result in re-duplication of some
of the logic that I recently refactored to be shared with the
v2 tick implementation.

The v2 tick implementation has the same edge case around
metadata, but cannot be easily adjusted to use the same
pattern.

So this commit sticks a comment in the code; nobody is using
v2 AFAIK, and there have been reports of some wonky behavior
with it.  My recommendation at this time is to avoid using
the v2 wheel and we can fix this all up for it later.
2025-04-04 15:52:17 -07:00
Wez Furlong a24ff89bd1 add some more error context to a couple of stack traces 2025-04-04 14:48:14 -07:00
Wez Furlong 3995e62a33 message: disambiguate "metadata must be loaded first" errors
We have a couple of different places that might emit it,
let's annotate each one so that we know where it might
be coming from.
2025-04-04 14:40:19 -07:00
Wez Furlong dce5dd3082 deps: update openssl 2025-04-04 13:58:40 -07:00
Wez Furlong d96758bc6d cargo update 2025-04-04 13:53:27 -07:00
Wez Furlong e7ca5b4424 docs: update changelog to reflect more of kcli top's new features 2025-04-04 13:51:34 -07:00
Wez Furlong 129dbac461 kcli/top: support fuzzy matching series and heatmap names
Press f to edit the filter, watch it fuzzy match as you type.
2025-04-04 13:49:44 -07:00
Wez Furlong a9a096e76b kcli/top: refactor keyboard input
Move processing into state; this will aid in a future commit.
2025-04-04 10:32:07 -07:00
Wez Furlong bb9d786c86 kcli/top: scroll to tab when switching tabs 2025-04-04 08:14:04 -07:00
Wez Furlong f3a84fd40f kci/top: shift most heatmap math to accumulator stage
No need to rebuild/recompute the full data on each render
2025-04-04 08:11:12 -07:00
Wez Furlong 319b83bf8f kcli top: improve avg/freq labels
Some of the series ended up with bland labels like "lua" with
no context.  Let's include the overall metric name for those.

The consequence of this is that the labels column gets wider,
but I think that now that we have scrolling, we can adjust
that presentation in a follow up commit.
2025-04-04 07:59:46 -07:00
Wez Furlong 04ea7e5804 kcli top: auto add all histograms 2025-04-04 07:49:50 -07:00
Wez Furlong cb1c87ab15 kcli top: initial support for showing heatmaps 2025-04-04 07:17:05 -07:00
Wez Furlong ad7e98e7c5 kcli top: add basic help tab 2025-04-03 14:57:51 -07:00