pub struct ScopedFlags { /* private fields */ }Expand description
Flags fixed on one scope, remembering what it has already resolved.
Build one per request — Flags::for_scope, or
FlagsExt::scoped_flags inside a handler — and ask it
everything. Each flag is resolved at most once for as long as the view
lives, so a resolver that costs a query costs it once however many times the
page asks.
The memory is a memo, not a lock: two tasks checking the same unresolved
flag on one clone may both run the resolver, and one of the two answers is
kept. Serialising them would mean holding a lock across the resolver’s
await — turning every slow resolver into a queue — to save a duplicated
call that produces the same answer anyway.
It is also not a cache with a lifetime. An override written after a
ScopedFlags has resolved a flag is not seen by that view; call
ScopedFlags::refresh or, more usually, let the request end.
Implementations§
Source§impl ScopedFlags
impl ScopedFlags
Sourcepub async fn values<I, S>(&self, flags: I) -> Result<BTreeMap<String, bool>>
pub async fn values<I, S>(&self, flags: I) -> Result<BTreeMap<String, bool>>
Several flags at once, in one pass.
The shape a template wants: hand it a map and let it ask by name,
rather than threading a bool per feature through the view model.
let flags = Flags::new().define("a", |_| async { true }).define("b", |_| async { false });
let values = flags.for_scope(Scope::user_id(41)).values(["a", "b"]).await.unwrap();
assert!(values["a"]);
assert!(!values["b"]);Resolved one after another rather than concurrently: a resolver that takes a database connection would otherwise take as many as there are flags on the page, all at once, which is how a feature-flag call turns into a connection-pool outage.
Sourcepub async fn all(&self) -> Result<BTreeMap<String, bool>>
pub async fn all(&self) -> Result<BTreeMap<String, bool>>
Every defined flag, for this scope.
Note the word: a flag that only exists as a stored override or a
flags.on entry is not in the list, because nothing has told this
process it exists. Use it for a debugging endpoint, not as the truth
about what the installation has switched on.
Sourcepub async fn any<I, S>(&self, flags: I) -> Result<bool>
pub async fn any<I, S>(&self, flags: I) -> Result<bool>
Whether any of these flags is on. Stops at the first one that is.
Sourcepub fn refresh(&self)
pub fn refresh(&self)
Forget what has been resolved, so the next check asks again.
For the one case that needs it: code that writes an override and then wants to see its own change through the same view.
Sourcepub fn resolved_count(&self) -> usize
pub fn resolved_count(&self) -> usize
How many flags this view has resolved so far. Tests use it to prove the memo exists; a debugging endpoint can show it.
Trait Implementations§
Source§impl Clone for ScopedFlags
impl Clone for ScopedFlags
Source§fn clone(&self) -> ScopedFlags
fn clone(&self) -> ScopedFlags
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more