use cache builder for row and table cache options

add cache check using multi-get path

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2025-01-18 01:34:14 +00:00
parent fc1170e12a
commit 96e85adc32
5 changed files with 90 additions and 34 deletions

View file

@ -3,6 +3,7 @@ use std::{convert::AsRef, fmt::Debug, io::Write, sync::Arc};
use arrayvec::ArrayVec;
use conduwuit::{err, implement, utils::result::MapExpect, Err, Result};
use futures::{future::ready, Future, FutureExt, TryFutureExt};
use rocksdb::{DBPinnableSlice, ReadOptions};
use serde::Serialize;
use tokio::task;
@ -90,6 +91,17 @@ where
.boxed()
}
/// Fetch a value from the cache without I/O.
#[implement(super::Map)]
#[tracing::instrument(skip(self, key), name = "cache", level = "trace")]
pub(crate) fn get_cached<K>(&self, key: &K) -> Result<Option<Handle<'_>>>
where
K: AsRef<[u8]> + Debug + ?Sized,
{
let res = self.get_blocking_opts(key, &self.cache_read_options);
cached_handle_from(res)
}
/// Fetch a value from the database into cache, returning a reference-handle.
/// The key is referenced directly to perform the query. This is a thread-
/// blocking call.
@ -99,37 +111,47 @@ pub fn get_blocking<K>(&self, key: &K) -> Result<Handle<'_>>
where
K: AsRef<[u8]> + ?Sized,
{
self.db
.db
.get_pinned_cf_opt(&self.cf(), key, &self.read_options)
let res = self.get_blocking_opts(key, &self.read_options);
handle_from(res)
}
#[implement(super::Map)]
fn get_blocking_opts<K>(
&self,
key: &K,
read_options: &ReadOptions,
) -> Result<Option<DBPinnableSlice<'_>>, rocksdb::Error>
where
K: AsRef<[u8]> + ?Sized,
{
self.db.db.get_pinned_cf_opt(&self.cf(), key, read_options)
}
#[inline]
pub(super) fn handle_from(
result: Result<Option<DBPinnableSlice<'_>>, rocksdb::Error>,
) -> Result<Handle<'_>> {
result
.map_err(map_err)?
.map(Handle::from)
.ok_or(err!(Request(NotFound("Not found in database"))))
}
/// Fetch a value from the cache without I/O.
#[implement(super::Map)]
#[tracing::instrument(skip(self, key), name = "cache", level = "trace")]
pub(crate) fn get_cached<K>(&self, key: &K) -> Result<Option<Handle<'_>>>
where
K: AsRef<[u8]> + Debug + ?Sized,
{
let res = self
.db
.db
.get_pinned_cf_opt(&self.cf(), key, &self.cache_read_options);
match res {
#[inline]
pub(super) fn cached_handle_from(
result: Result<Option<DBPinnableSlice<'_>>, rocksdb::Error>,
) -> Result<Option<Handle<'_>>> {
match result {
// cache hit; not found
| Ok(None) => Err!(Request(NotFound("Not found in database"))),
// cache hit; value found
| Ok(Some(res)) => Ok(Some(Handle::from(res))),
| Ok(Some(result)) => Ok(Some(Handle::from(result))),
// cache miss; unknown
| Err(e) if is_incomplete(&e) => Ok(None),
| Err(error) if is_incomplete(&error) => Ok(None),
// some other error occurred
| Err(e) => or_else(e),
| Err(error) => or_else(error),
}
}

View file

@ -1,7 +1,7 @@
use std::{convert::AsRef, fmt::Debug, sync::Arc};
use conduwuit::{
err, implement,
implement,
utils::{
stream::{automatic_amplification, automatic_width, WidebandExt},
IterStream,
@ -9,9 +9,11 @@ use conduwuit::{
Result,
};
use futures::{Stream, StreamExt, TryStreamExt};
use rocksdb::{DBPinnableSlice, ReadOptions};
use serde::Serialize;
use crate::{keyval::KeyBuf, ser, util::map_err, Handle};
use super::get::{cached_handle_from, handle_from};
use crate::{keyval::KeyBuf, ser, Handle};
#[implement(super::Map)]
#[tracing::instrument(skip(self, keys), level = "trace")]
@ -66,12 +68,40 @@ where
.try_flatten()
}
#[implement(super::Map)]
#[tracing::instrument(name = "batch_cached", level = "trace", skip_all)]
pub(crate) fn get_batch_cached<'a, I, K>(
&self,
keys: I,
) -> impl Iterator<Item = Result<Option<Handle<'_>>>> + Send
where
I: Iterator<Item = &'a K> + ExactSizeIterator + Send,
K: AsRef<[u8]> + Send + ?Sized + Sync + 'a,
{
self.get_batch_blocking_opts(keys, &self.cache_read_options)
.map(cached_handle_from)
}
#[implement(super::Map)]
#[tracing::instrument(name = "batch_blocking", level = "trace", skip_all)]
pub(crate) fn get_batch_blocking<'a, I, K>(
&self,
keys: I,
) -> impl Iterator<Item = Result<Handle<'_>>> + Send
where
I: Iterator<Item = &'a K> + ExactSizeIterator + Send,
K: AsRef<[u8]> + Send + ?Sized + Sync + 'a,
{
self.get_batch_blocking_opts(keys, &self.read_options)
.map(handle_from)
}
#[implement(super::Map)]
fn get_batch_blocking_opts<'a, I, K>(
&self,
keys: I,
read_options: &ReadOptions,
) -> impl Iterator<Item = Result<Option<DBPinnableSlice<'_>>, rocksdb::Error>> + Send
where
I: Iterator<Item = &'a K> + ExactSizeIterator + Send,
K: AsRef<[u8]> + Send + ?Sized + Sync + 'a,
@ -80,15 +110,8 @@ where
// comparator**.
const SORTED: bool = false;
let read_options = &self.read_options;
self.db
.db
.batched_multi_get_cf_opt(&self.cf(), keys, SORTED, read_options)
.into_iter()
.map(|result| {
result
.map_err(map_err)?
.map(Handle::from)
.ok_or(err!(Request(NotFound("Not found in database"))))
})
}