Variant identity: the object key under which a rendered variant is cached.
A variant is exactly its normalized processing options plus the source it was rendered from, so the key is
lowercase-hex(SHA-256(normalized-options ‖ "\n" ‖ canonical-source))The newline separates the two halves unambiguously. That is only sound
because a normalized options string cannot contain one:
AudioProxy.Options rejects control characters in dl and cb, the only
two options whose values are opaque, and every other value is drawn from a
fixed alphabet. Without the separator, ("", "/gain:3") and ("gain:3", "")
would hash identical bytes.
Equal variants therefore share a key regardless of segment order, and any
differing option (cb included, since it survives normalization) yields a
different one.
The digest is flat and length-bounded, which is what an S3 object key wants; a human-debuggable prefix was considered and rejected (design).
iex> AudioProxy.CacheKey.derive!("br:96/f:opus", "s3://masters/a.wav")
...> == AudioProxy.CacheKey.derive!("f:opus/br:96", "s3://masters/a.wav")
true
Summary
Functions
Derives the cache key for options rendered from source.
Like derive/2, raising ArgumentError when the options are invalid.
Types
@type t() :: String.t()
Lowercase hex SHA-256 digest, 64 characters.
Functions
@spec derive(AudioProxy.Options.t() | String.t() | [String.t()], String.t()) :: {:ok, t()} | {:error, AudioProxy.OptionError.t()}
Derives the cache key for options rendered from source.
options may be an options string, a pre-split segment list, or an already
parsed AudioProxy.Options.t/0. Every form is validated before it is
hashed — including the struct, which is not assumed to have come from
AudioProxy.Options.parse/1 — so no options that describe an unrenderable
variant can acquire a cache key.
source is the canonical source identity produced by the source resolver
(e.g. "s3://bucket/key") — this module does not canonicalize it.
@spec derive!(AudioProxy.Options.t() | String.t() | [String.t()], String.t()) :: t()
Like derive/2, raising ArgumentError when the options are invalid.
For call sites that have already validated their options — tests, and the render path once the request has passed the options gate.