1 unstable release
Uses new Rust 2024
| 0.1.0 | Dec 28, 2025 |
|---|
#788 in Procedural macros
81KB
1.5K
SLoC
picante
picante is an async incremental query runtime for Rust, inspired by Salsa but built for Tokio-first pipelines (like Dodeca).
What it has today
- Inputs (
InputIngredient<K, V>), interning (InternedIngredient<K>), and derived async queries (DerivedIngredient<DB, K, V>) - Dependency tracking via Tokio task-locals
- Per-task cycle detection (fast path)
- Async single-flight memoization per
(kind, key) - Cache persistence to disk (snapshot file) using
facet+facet-postcard(no serde) - Runtime notifications for live reload (
Runtime::subscribe_revisions,Runtime::subscribe_events)
Quickstart (minimal)
use picante::{DerivedIngredient, DynIngredient, HasRuntime, IngredientLookup, IngredientRegistry, InputIngredient, QueryKindId, Runtime};
use std::sync::Arc;
#[derive(Default)]
struct Db {
runtime: Runtime,
ingredients: IngredientRegistry<Db>,
}
impl HasRuntime for Db {
fn runtime(&self) -> &Runtime {
&self.runtime
}
}
impl IngredientLookup for Db {
fn ingredient(&self, kind: QueryKindId) -> Option<&dyn DynIngredient<Self>> {
self.ingredients.ingredient(kind)
}
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> picante::PicanteResult<()> {
let db = Db::default();
let text: Arc<InputIngredient<String, String>> =
Arc::new(InputIngredient::new(QueryKindId(1), "Text"));
let len: Arc<DerivedIngredient<Db, String, u64>> = {
let text = text.clone();
Arc::new(DerivedIngredient::new(QueryKindId(2), "Len", move |db, key| {
let text = text.clone();
Box::pin(async move {
let s = text.get(db, &key)?.unwrap_or_default();
Ok(s.len() as u64)
})
}))
};
text.set(&db, "a".into(), "hello".into());
assert_eq!(len.get(&db, "a".into()).await?, 5);
Ok(())
}
Persistence (snapshot cache)
picante can save/load inputs and memoized derived values (including dependency lists):
use picante::persist::{load_cache, save_cache};
// save_cache(path, db.runtime(), &[&*text, &*len]).await?;
// load_cache(path, db.runtime(), &[&*text, &*len]).await?;
If you need cache size limits or custom corruption handling, use:
save_cache_with_optionsload_cache_with_options
Notes
- Tokio-only: query execution uses Tokio task-local context.
- Global invalidation v1: changing any input bumps a single global
Revision. - Compile-time optimized: derived query state machine uses trait objects to avoid monomorphization bloat (96% IR reduction, 36% faster builds). Small runtime cost (vtable dispatch + boxed futures) for large compile-time win. See architecture docs for details.
License
Licensed under either of Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0) or MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT) at your option.
Dependencies
~420KB