Per-app Fly-token resolver.
One AppServer process exists per Fly app that has ever been asked for a
token. The process owns the full resolution chain for its app:
- ETS cache re-check (in case a concurrent caller won the race).
ExAtlas.Fly.TokenStorage(durable).~/.fly/config.yml.fly tokens create readonly(CLI).- Manual-override token (last-resort storage lookup).
The shared ETS table is owned by ExAtlas.Fly.Tokens.ETSOwner; this server
writes into it but does not own it. That split is what lets per-app crashes
stay scoped (DynamicSupervisor :one_for_one) while still preserving the
cache for sibling apps.
Runtime options (for test injection)
:app_name(required) — the Fly app this server tracks.:registry(required) — theRegistryname used for{:via, ...}naming.:task_sup—Task.Supervisorname used to offload non-blocking persist writes. Optional; when omitted, persist runs inline (synchronous) which is fine for tests without a Task.Supervisor in scope.:table_name— override the ETS table to write into.:cmd_fn— replacesSystem.cmd/3.:config_file_fn— replaces the~/.fly/config.ymlreader.:storage_mod— replaces the storage module.:ttl_seconds— token TTL (default 24h).:cli_timeout_ms—fly tokens createtimeout (default 15s).:soft_expiry_lead_seconds— how far beforeexpires_atto schedule a background refresh (default 3600). Set to0to disable.
Summary
Functions
Resolve a token for this AppServer's app. Returns {result, source}.
Returns a specification to start this module under a supervisor.
Invalidate this AppServer's ETS entry.
Atomic invalidate-then-acquire. Equivalent to invalidate/1 followed by
acquire/1, but executed under a single handle_call so no concurrent caller
can acquire between the two and see the pre-refresh token.
Persist a manual-override token for this AppServer's app.
Functions
Resolve a token for this AppServer's app. Returns {result, source}.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec invalidate(pid()) :: :ok
Invalidate this AppServer's ETS entry.
Atomic invalidate-then-acquire. Equivalent to invalidate/1 followed by
acquire/1, but executed under a single handle_call so no concurrent caller
can acquire between the two and see the pre-refresh token.
Returns the same {result, source} tuple as acquire/1.
Persist a manual-override token for this AppServer's app.
Returns {:error, {:persist_failed, reason}} if the storage backend raises —
manual tokens are not re-acquirable, so the failure is surfaced rather than
silently logged.