Problem
ConfigStore::get behaves differently across adapters for the same logical call:
- Fastly (
crates/edgezero-adapter-fastly/src/config_store.rs): get pipes every value through resolve_fastly_config_value, which requires the value to be a BlobEnvelope or a chunk pointer. A root value that is neither is rejected as an error.
- Axum (
crates/edgezero-adapter-axum/src/config_store.rs): get is a plain passthrough (Ok(self.data.get(key).cloned())).
- Cloudflare: also a plain passthrough.
So the same ConfigStore::get(key) against the same logical store id succeeds on Axum/Cloudflare and errors on Fastly, purely because the stored value is a plain string rather than an envelope.
Why this bites
The app-config blob store legitimately holds a BlobEnvelope (and chunk pointers), so envelope resolution makes sense there. But apps also use other config stores that hold plain values — key material, ID lists, CIDR lists, feature flags. Binding those store ids to the Fastly ConfigStore makes every read fail, while the identical code path works on the other adapters.
The practical effect is that ConfigStore is only usable on Fastly for envelope-shaped stores, which is not obvious from the trait or its docs — the asymmetry is discovered at runtime, per adapter.
Ask
Make the behavior consistent, e.g. one of:
- Preferred: keep
ConfigStore::get a plain passthrough on every adapter, and expose envelope/chunk resolution as an explicit, opt-in layer (a wrapper store or a separate method) that callers apply to the store that actually holds an envelope.
- Have Fastly's
get fall back to returning the raw value when it is neither an envelope nor a chunk pointer, rather than erroring.
- At minimum, document the asymmetry prominently on the trait and adapter impls, so callers know a Fastly
ConfigStore is envelope-only.
Workaround (downstream)
We bind only the app-config (envelope) store id to the chunk-aware Fastly ConfigStore, and bind every other config store id to a local plain ConfigStore over fastly::ConfigStore::try_get. It works, but it means we cannot use the provided store uniformly across our declared config ids.
Problem
ConfigStore::getbehaves differently across adapters for the same logical call:crates/edgezero-adapter-fastly/src/config_store.rs):getpipes every value throughresolve_fastly_config_value, which requires the value to be aBlobEnvelopeor a chunk pointer. A root value that is neither is rejected as an error.crates/edgezero-adapter-axum/src/config_store.rs):getis a plain passthrough (Ok(self.data.get(key).cloned())).So the same
ConfigStore::get(key)against the same logical store id succeeds on Axum/Cloudflare and errors on Fastly, purely because the stored value is a plain string rather than an envelope.Why this bites
The app-config blob store legitimately holds a
BlobEnvelope(and chunk pointers), so envelope resolution makes sense there. But apps also use other config stores that hold plain values — key material, ID lists, CIDR lists, feature flags. Binding those store ids to the FastlyConfigStoremakes every read fail, while the identical code path works on the other adapters.The practical effect is that
ConfigStoreis only usable on Fastly for envelope-shaped stores, which is not obvious from the trait or its docs — the asymmetry is discovered at runtime, per adapter.Ask
Make the behavior consistent, e.g. one of:
ConfigStore::geta plain passthrough on every adapter, and expose envelope/chunk resolution as an explicit, opt-in layer (a wrapper store or a separate method) that callers apply to the store that actually holds an envelope.getfall back to returning the raw value when it is neither an envelope nor a chunk pointer, rather than erroring.ConfigStoreis envelope-only.Workaround (downstream)
We bind only the app-config (envelope) store id to the chunk-aware Fastly
ConfigStore, and bind every other config store id to a local plainConfigStoreoverfastly::ConfigStore::try_get. It works, but it means we cannot use the provided store uniformly across our declared config ids.