aws/internal/credentials_cache
Credentials cache: a gleam_otp actor that owns a Provider and caches
the last successful Credentials. Re-fetches when the cached value is
within buffer_seconds of its expires_at, or when the cache is empty
(first call) or the previous fetch failed.
Non-expiring credentials (expires_at = None) are cached forever — env
vars don’t rotate without a process restart, so re-reading them on every
signed request would be wasteful.
Concurrency: actor messages are handled sequentially, so two parallel
get calls during the first fetch coalesce into a single provider
invocation. No thundering-herd shielding beyond that — adequate for the
rates AWS SDKs see in practice.
Types
Values
pub fn as_provider(cache: Cache) -> credentials.Provider
Re-expose the cache as a regular Provider. The returned provider’s
fetch closure proxies to get(cache) — so the rest of the SDK can
thread Provider values around as before, but now hot-path reads
debounce into the actor and avoid re-running the seven-stage chain
on every signed request.
pub const default_buffer_seconds: Int
Default refresh buffer: trigger a refresh five minutes before expiry. Tracks the conservative value most AWS SDKs use.
pub fn get(
cache: Cache,
) -> Result(credentials.Credentials, credentials.ProviderError)
Fetch the current credentials, refreshing from the wrapped provider if the cache is empty or the credentials are within the refresh buffer of expiry. Returns whatever the provider produced — the cache itself never fabricates errors.
pub fn shutdown(cache: Cache) -> Nil
Tell the cache actor to exit. Fire-and-forget. See
aws/internal/actor_lifecycle.shutdown_via_stop for the contract;
idempotent because Erlang silently drops sends to a dead Pid.
pub fn shutdown_sync(
cache: Cache,
timeout_ms: Int,
) -> Result(Nil, Nil)
Synchronous teardown — monitors the actor, sends Stop, waits for
DOWN. Ok(Nil) on clean exit, Error(Nil) only on real timeout.
Already-dead actors short-circuit to Ok(Nil) via
subject_owner returning Error.
pub fn start(
provider provider: credentials.Provider,
clock clock: fn() -> Int,
buffer_seconds buffer_seconds: Int,
) -> Result(Cache, StartError)
Start the cache actor.
provider: the upstream provider this cache wraps. Can itself be acredentials.chain([...])— the cache doesn’t care.clock: returns unix seconds. The default production wiring useserlang:system_time(second); tests pass a closure over a controlled counter so they can fast-forward across expiries.buffer_seconds: trigger a refresh this many seconds beforeexpires_at. Seedefault_buffer_seconds.
pub fn start_default(
provider provider: credentials.Provider,
) -> Result(Cache, StartError)
Start a cache using the OS clock and default_buffer_seconds. For
production wiring this is almost always what you want.