pub trait Query:
Clone
+ Send
+ Sync
+ 'static {
type CacheKey: Key;
type Output: Send + Sync + 'static;
// Required methods
fn cache_key(&self) -> Self::CacheKey;
fn query(
&self,
ctx: &mut QueryContext<'_>,
) -> Result<Self::Output, QueryError>;
fn output_eq(old: &Self::Output, new: &Self::Output) -> bool;
// Provided method
fn durability(&self) -> u8 { ... }
}Expand description
A query that can be executed and cached.
Queries are the fundamental unit of computation in query-flow. Each query:
- Has a cache key that uniquely identifies the computation
- Produces an output value
- Can depend on other queries via
QueryContext::query()
§Sync by Design
The query method is intentionally synchronous. This avoids the “function
coloring” problem where async infects the entire call stack. For async
operations, use the suspense pattern with AssetLoadingState.
§Error Handling
The query method returns Result<Output, QueryError> where:
QueryErrorrepresents system errors (Suspend, Cycle, Cancelled)- User domain errors should be wrapped in
Output, e.g.,type Output = Result<T, MyError>
This means fallible queries return Ok(Ok(value)) on success and Ok(Err(error)) on user error.
§Example
use query_flow::{Query, QueryContext, QueryError, Key};
// Simple infallible query
struct Add { a: i32, b: i32 }
impl Query for Add {
type CacheKey = (i32, i32);
type Output = i32;
fn cache_key(&self) -> Self::CacheKey {
(self.a, self.b)
}
fn query(&self, _ctx: &mut QueryContext) -> Result<Self::Output, QueryError> {
Ok(self.a + self.b)
}
}
// Fallible query with user errors
struct ParseInt { input: String }
impl Query for ParseInt {
type CacheKey = String;
type Output = Result<i32, std::num::ParseIntError>;
fn cache_key(&self) -> Self::CacheKey {
self.input.clone()
}
fn query(&self, _ctx: &mut QueryContext) -> Result<Self::Output, QueryError> {
Ok(self.input.parse()) // Ok(Ok(n)) or Ok(Err(parse_error))
}
}Required Associated Types§
Required Methods§
Sourcefn query(&self, ctx: &mut QueryContext<'_>) -> Result<Self::Output, QueryError>
fn query(&self, ctx: &mut QueryContext<'_>) -> Result<Self::Output, QueryError>
Sourcefn output_eq(old: &Self::Output, new: &Self::Output) -> bool
fn output_eq(old: &Self::Output, new: &Self::Output) -> bool
Compare two outputs for equality (for early cutoff optimization).
When a query is recomputed and the output is equal to the previous output, downstream queries can skip recomputation (early cutoff).
The #[query] macro generates this using PartialEq by default.
Use output_eq = custom_fn for types without PartialEq.
Provided Methods§
Sourcefn durability(&self) -> u8
fn durability(&self) -> u8
Durability hint for this query.
Higher values indicate the query’s output changes less frequently. This is used for optimization in the dependency tracking layer.
- 0: Volatile (changes frequently)
- Higher: More stable
Default: 0 (volatile)
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.