Persists captured emails off the process that sent them.
SquatchMail.Capture's telemetry handler runs synchronously in the
caller's process — the same process that just called
Mailer.deliver/2 — so it must return immediately. It hands each captured
email's attrs to this GenServer with GenServer.cast/2 (never call/2,
which would block the caller waiting for a reply) and this process does
the actual SquatchMail.Tracker.record_email/1 write, off the caller.
Backpressure
Two independent limits bound the work this GenServer takes on, so a burst of sends can't turn into unbounded memory growth or a flooded database connection pool:
SquatchMail.Config.max_queue/0(default10_000) bounds how many captures may be waiting (queued in this process's own FIFO queue, not yet handed to a worker). Once the number of queued-plus-in-flight captures reaches this limit, new captures are dropped outright:[:squatch_mail, :capture, :dropped]fires and a warning logs — at most once a minute, so a sustained overload doesn't itself become a logging flood.SquatchMail.Config.max_concurrency/0(default50) bounds how many captures are being persisted at once. Each in-flight persist checks out a connection from the host'sRepopool; without this cap, a burst large enough to exceed:max_queuewould also be large enough to try to check out thousands of connections simultaneously and starve every other query the host app is running. Workers are unlinked (Task.Supervisor.async_nolink/2) so one crashing persist can't take this GenServer down with it.
Queued work is drained into new workers as running ones finish, so the
effective throughput is :max_concurrency persists in flight at any given
moment, with up to :max_queue more waiting their turn.
Summary
Functions
Returns a specification to start this module under a supervisor.
Enqueues an email's attrs for persistence.
Starts the recorder. Only one is expected per application (registered under this module's name).
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec record(map()) :: :ok
Enqueues an email's attrs for persistence.
Non-blocking: returns immediately regardless of whether the attrs were accepted, queued, or dropped for being over capacity.
@spec start_link(Keyword.t()) :: GenServer.on_start()
Starts the recorder. Only one is expected per application (registered under this module's name).