AudioProxy.CacheKey (audio_proxy v0.4.0)

Copy Markdown View Source

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

Types

t()

Lowercase hex SHA-256 digest, 64 characters.

Functions

Derives the cache key for options rendered from source.

Like derive/2, raising ArgumentError when the options are invalid.

Types

t()

@type t() :: String.t()

Lowercase hex SHA-256 digest, 64 characters.

Functions

derive(options, source)

@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.

derive!(options, source)

@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.