Tracks how well outbound sending is going, and decides when to trip the guard.
Owns the send_health field of the session state: error and drop counters,
the one-minute rolling windows behind the per-minute thresholds, and the
paused/hard-stopped gates that block sending.
Deciding is separate from acting: guard_trigger_reason/2 is pure and answers
"have we crossed a threshold", while stopping or disconnecting the session
stays with ExWapp.Session.Worker, which owns the transport and the process.
Summary
Functions
Publishes a health event, never failing the caller if delivery breaks.
Clears the consecutive-error streak after a send finally succeeds.
The counters a fresh session starts from.
Rejects a send while the guard holds the session paused or hard-stopped.
Reads one counter, falling back to default when it was never set.
The three numbers the guard thresholds are compared against.
Names the threshold that has been crossed, or nil while all are within range.
Adds to one counter, treating a missing counter as zero.
Records an outbound-queue failure, which is counted apart from send errors.
Writes one counter.
Records a message dropped after its confirmation never arrived.
Records a failed send and broadcasts it to health subscribers.
Types
@type metrics() :: %{ consecutive: non_neg_integer(), errors_min: non_neg_integer(), drops_min: non_neg_integer() }
@type trigger_reason() :: {atom(), non_neg_integer()} | nil
Functions
@spec broadcast_event(ExWapp.Session.Worker.t(), atom(), map()) :: :ok
Publishes a health event, never failing the caller if delivery breaks.
@spec clear_consecutive_send_errors(ExWapp.Session.Worker.t()) :: ExWapp.Session.Worker.t()
Clears the consecutive-error streak after a send finally succeeds.
@spec default() :: map()
The counters a fresh session starts from.
@spec ensure_send_enabled(ExWapp.Session.Worker.t(), String.t()) :: {:ok, ExWapp.Session.Worker.t()} | {:error, atom(), ExWapp.Session.Worker.t()}
Rejects a send while the guard holds the session paused or hard-stopped.
A rejection is itself recorded as a send error, so repeated attempts against a closed gate keep the counters honest.
@spec get(ExWapp.Session.Worker.t(), atom(), term()) :: term()
Reads one counter, falling back to default when it was never set.
@spec guard_metrics(ExWapp.Session.Worker.t()) :: metrics()
The three numbers the guard thresholds are compared against.
@spec guard_trigger_reason(metrics(), map()) :: trigger_reason()
Names the threshold that has been crossed, or nil while all are within range.
Pure: given the metrics and the configured limits it decides nothing else.
@spec increment(ExWapp.Session.Worker.t(), atom(), integer()) :: ExWapp.Session.Worker.t()
Adds to one counter, treating a missing counter as zero.
@spec increment_outbound_queue_errors(ExWapp.Session.Worker.t(), term()) :: ExWapp.Session.Worker.t()
Records an outbound-queue failure, which is counted apart from send errors.
@spec put(ExWapp.Session.Worker.t(), atom(), term()) :: ExWapp.Session.Worker.t()
Writes one counter.
@spec register_drop_timeout(ExWapp.Session.Worker.t(), String.t(), map()) :: ExWapp.Session.Worker.t()
Records a message dropped after its confirmation never arrived.
@spec register_send_error(ExWapp.Session.Worker.t(), term(), map()) :: ExWapp.Session.Worker.t()
Records a failed send and broadcasts it to health subscribers.