AuroraMeter.Events.Gate (Aurora Meter v1.0.0)

View Source

Internal. Not part of the supported API (see API inventory). It may change in any release, including a patch.

Admission control for the durable write path: at most :record_max_concurrency callers may hold a connection and an open transaction at once, and the rest are told :overloaded rather than queued behind a pool checkout that will time out somewhere unhelpful.

Why a process and not a counter

:counters would be cheaper and is wrong here. A caller that is killed with :kill runs no after block and no on_exit, so its permit would never be returned and the loss would be permanent: after enough kills the gate would refuse everything for ever. A process can monitor its callers, so a permit comes back when the caller dies however it dies.

There is no clock in this module

A concurrency limit at this timescale must not be decided by comparing two wall-clock instants: the shared database clock steps backwards by hundreds of milliseconds on this hardware (open-findings.md X100), and a node clock is worse. So the gate counts and monitors; it never expires anything. The only time value here is the GenServer.call/3 timeout, which is OTP's own monotonic timer and not a comparison of two stamped instants, and a caller whose call times out is refused rather than admitted.

Summary

Types

A permit. Hand it back to leave/1 when the work is done.

Functions

How many callers are admitted right now. For tests and for AuroraMeter.Operations.

Returns a specification to start this module under a supervisor.

Asks for a permit.

Returns a permit. Safe to call with a permit that has already been released.

Types

permit()

@type permit() :: reference()

A permit. Hand it back to leave/1 when the work is done.

Functions

admitted()

@spec admitted() :: non_neg_integer()

How many callers are admitted right now. For tests and for AuroraMeter.Operations.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

enter()

@spec enter() :: {:ok, permit()} | {:error, :overloaded | :unavailable}

Asks for a permit.

{:ok, permit} admits the caller and monitors it. {:error, :overloaded} means :record_max_concurrency callers are already admitted. {:error, :unavailable} means the gate did not answer: it is restarting, or it is too busy to reply within 5000 ms. Neither is a reason to fall back to buffered tracking (L-03b-4).

leave(permit)

@spec leave(permit()) :: :ok

Returns a permit. Safe to call with a permit that has already been released.