asobi_auth_cache (asobi v0.35.4)

View Source

In-memory cache for access-token → player resolution.

The WS connect path and every authenticated HTTP request hit nova_auth_refresh:get_user_by_access_token/2, which costs two kura queries (one for the token row, one for the user). Under mobile-reconnect storms this is the dominant per-connect cost. The cache turns a hit into one ETS lookup.

Lifetime and freshness

Entries TTL after asobi.auth_cache_ttl_ms (default 60_000ms) so a revoked token's fallout is bounded. Invalidation must be wired into every code path that deletes or replaces a token; see invalidate/1.

Negative results (token not found, expired) are also cached but with a much shorter TTL (asobi.auth_cache_negative_ttl_ms, default 5_000ms) so a fresh-token race doesn't keep returning errors after the token actually exists.

Process model

A single named gen_server owns the ETS table. Lookups are direct ETS reads from any process; writes go through the gen_server only for expiry-sweep coordination — put/2,3 and invalidate/1 write directly via public ETS for latency. The gen_server runs a periodic sweep (every TTL/2) that removes expired rows so the table doesn't grow unbounded under attack.

Summary

Functions

clear()

-spec clear() -> ok.

handle_call(Req, From, State)

-spec handle_call(term(), gen_server:from(), map()) -> {reply, ok, map()}.

handle_cast(Msg, State)

-spec handle_cast(term(), map()) -> {noreply, map()}.

handle_info/2

-spec handle_info(term(), map()) -> {noreply, map()}.

info()

-spec info() -> #{size := non_neg_integer(), memory_words := non_neg_integer()}.

init/1

-spec init([]) -> {ok, map()}.

invalidate/1

-spec invalidate(binary()) -> ok.

put_negative(Token)

-spec put_negative(binary()) -> ok.

put_positive(Token, Player)

-spec put_positive(binary(), map()) -> ok.

resolve_token/1

-spec resolve_token(binary()) -> {ok, map()} | {error, term()}.

start_link()

-spec start_link() -> gen_server:start_ret().