pub trait KvHandle:
Send
+ Sync
+ 'static {
// Required methods
fn get<'a>(
&'a self,
key: &'a str,
) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>>> + Send + 'a>>;
fn set<'a>(
&'a self,
key: &'a str,
value: &'a [u8],
ttl: Option<Duration>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
fn set_if_absent<'a>(
&'a self,
key: &'a str,
value: &'a [u8],
ttl: Option<Duration>,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'a>>;
fn delete<'a>(
&'a self,
key: &'a str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'a>>;
fn increment<'a>(
&'a self,
key: &'a str,
delta: i64,
ttl: Option<Duration>,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'a>>;
}Expand description
Trait for accessing the KV store from handler contexts.
Defined in forge-core so all context types can hold a dyn KvHandle
without depending on forge-runtime. The runtime implements this trait
on KvStore and threads it into every context at construction time.
The KV store is namespaced: each handle was created with a namespace prefix that scopes all keys, preventing collisions between subsystems.
§Example
use std::time::Duration;
#[forge::query]
pub async fn get_feature_flag(ctx: &QueryContext, flag: String) -> Result<bool> {
let raw = ctx.kv().get(&flag).await?;
Ok(raw.map(|b| b == b"true").unwrap_or(false))
}
#[forge::mutation]
pub async fn set_feature_flag(ctx: &MutationContext, flag: String, enabled: bool) -> Result<()> {
let value = if enabled { b"true".as_ref() } else { b"false".as_ref() };
ctx.kv().set(&flag, value, None).await
}Required Methods§
Sourcefn get<'a>(
&'a self,
key: &'a str,
) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>>> + Send + 'a>>
fn get<'a>( &'a self, key: &'a str, ) -> Pin<Box<dyn Future<Output = Result<Option<Vec<u8>>>> + Send + 'a>>
Get a value by key. Returns None if the key doesn’t exist or is expired.
Sourcefn set<'a>(
&'a self,
key: &'a str,
value: &'a [u8],
ttl: Option<Duration>,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>
fn set<'a>( &'a self, key: &'a str, value: &'a [u8], ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>
Set a key to a value, optionally with a TTL. Overwrites any existing value.
Sourcefn set_if_absent<'a>(
&'a self,
key: &'a str,
value: &'a [u8],
ttl: Option<Duration>,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'a>>
fn set_if_absent<'a>( &'a self, key: &'a str, value: &'a [u8], ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'a>>
Set a key only if it doesn’t already exist (or is expired).
Returns true if the value was stored, false if a live entry already existed.
Sourcefn delete<'a>(
&'a self,
key: &'a str,
) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'a>>
fn delete<'a>( &'a self, key: &'a str, ) -> Pin<Box<dyn Future<Output = Result<bool>> + Send + 'a>>
Delete a key. Returns true if the key existed.
Sourcefn increment<'a>(
&'a self,
key: &'a str,
delta: i64,
ttl: Option<Duration>,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'a>>
fn increment<'a>( &'a self, key: &'a str, delta: i64, ttl: Option<Duration>, ) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'a>>
Atomically increment a counter by delta.
Creates the counter at 0 if it doesn’t exist. Returns the new value.
Expired counters are treated as non-existent (the value resets to delta).
When ttl is None, an existing counter’s TTL is preserved.