aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-02-26 12:47:40 +0100
committermetamuffin <metamuffin@disroot.org>2026-02-26 12:47:40 +0100
commit4ba86694e393c61107e27c4127efc0455b329524 (patch)
treeca6ab8bf0ccae5c26180247239fffde261a2d3ba
parenteb6648770e7de66ccafe44d114ecbb2c1eaf444d (diff)
downloadjellything-4ba86694e393c61107e27c4127efc0455b329524.tar
jellything-4ba86694e393c61107e27c4127efc0455b329524.tar.bz2
jellything-4ba86694e393c61107e27c4127efc0455b329524.tar.zst
db continuation
-rw-r--r--database/src/kv/index.rs61
-rw-r--r--database/src/kv/mod.rs7
-rw-r--r--server/src/ui/items.rs6
3 files changed, 47 insertions, 27 deletions
diff --git a/database/src/kv/index.rs b/database/src/kv/index.rs
index 60d291c..ee14d77 100644
--- a/database/src/kv/index.rs
+++ b/database/src/kv/index.rs
@@ -13,7 +13,7 @@ use crate::{
prefix_iterator::PrefixIterator,
},
};
-use anyhow::Result;
+use anyhow::{Result, bail};
use jellyobject::Object;
use std::iter::empty;
@@ -86,22 +86,31 @@ pub fn iter_index<'a>(
txn: &'a dyn jellykv::Transaction,
prefix: Vec<u8>,
sort: &Sort,
+ resume: Option<Vec<u8>>,
) -> Result<Box<dyn Iterator<Item = Result<(RowNum, Vec<u8>)>> + 'a>> {
Ok(match sort {
- Sort::None => Box::new(
- PrefixIterator {
- inner: txn.iter(&prefix, false)?,
- prefix: prefix.into(),
+ Sort::None => {
+ let mut start = prefix.clone();
+ if let Some(resume) = resume {
+ if resume.len() != 8 {
+ bail!("invalid resume length")
+ }
+ start.extend(resume);
+ start = inc_key(start);
}
- .map(|k| {
- k.map(|k| {
- (
- RowNum::from_be_bytes(k[k.len() - 8..].try_into().unwrap()),
- k[4..].to_vec(),
- )
- })
- }),
- ),
+ Box::new(
+ PrefixIterator {
+ inner: txn.iter(&start, false)?,
+ prefix: prefix.into(),
+ }
+ .map(|k| {
+ k.map(|k| {
+ let rn = RowNum::from_be_bytes(k[k.len() - 8..].try_into().unwrap());
+ (rn, rn.to_be_bytes().to_vec())
+ })
+ }),
+ )
+ }
Sort::Random(seed) => {
let mut k = prefix.clone();
k.extend(randomize(*seed).to_be_bytes());
@@ -118,19 +127,27 @@ pub fn iter_index<'a>(
}
Sort::Value(value_sort) => {
assert!(value_sort.offset.is_none(), "TODO");
+ let mut start = prefix.clone();
+ if let Some(resume) = resume {
+ if resume.len() != 8 {
+ bail!("invalid resume length")
+ }
+ start.extend(resume);
+ start = inc_key(start);
+ }
Box::new(
PrefixIterator {
inner: match value_sort.order {
- SortOrder::Ascending => txn.iter(&prefix, false)?,
- SortOrder::Descending => txn.iter(&prefix_end(prefix.clone()), true)?,
+ SortOrder::Ascending => txn.iter(&start, false)?,
+ SortOrder::Descending => txn.iter(&inc_key(prefix.clone()), true)?,
},
- prefix: prefix.into(),
+ prefix: prefix.clone().into(),
}
- .map(|k| {
+ .map(move |k| {
k.map(|k| {
(
RowNum::from_be_bytes(k[k.len() - 8..].try_into().unwrap()),
- k[4..].to_vec(),
+ k[prefix.len()..].to_vec(),
)
})
}),
@@ -140,15 +157,15 @@ pub fn iter_index<'a>(
})
}
-fn prefix_end(mut prefix: Vec<u8>) -> Vec<u8> {
- for v in prefix.iter_mut().rev() {
+fn inc_key(mut k: Vec<u8>) -> Vec<u8> {
+ for v in k.iter_mut().rev() {
let (nv, carry) = v.overflowing_add(1);
*v = nv;
if !carry {
break;
}
}
- prefix
+ k
}
fn randomize(mut x: u64) -> u64 {
diff --git a/database/src/kv/mod.rs b/database/src/kv/mod.rs
index 69e9c3b..837aa51 100644
--- a/database/src/kv/mod.rs
+++ b/database/src/kv/mod.rs
@@ -111,7 +111,12 @@ impl Transaction for &mut dyn jellykv::Transaction {
}
let mut iters = Vec::new();
for prefix in prefixes {
- iters.push(iter_index(*self, prefix, &query.sort)?)
+ iters.push(iter_index(
+ *self,
+ prefix,
+ &query.sort,
+ query.continuation.clone(),
+ )?)
}
if iters.len() == 1 {
return Ok(iters.pop().unwrap());
diff --git a/server/src/ui/items.rs b/server/src/ui/items.rs
index 6383830..286fc01 100644
--- a/server/src/ui/items.rs
+++ b/server/src/ui/items.rs
@@ -25,16 +25,14 @@ pub fn r_items(ri: RequestInfo, cont: Option<&str>) -> MyResult<UiResponse> {
ri.state.database.transaction(&mut |txn| {
let rows = txn
.query(Query {
- filter: Filter::Has(Path(vec![NO_SLUG.0])),
+ filter: Filter::Match(Path(vec![NO_KIND.0]), KIND_CHANNEL.into()),
continuation: cont.clone(),
..Default::default()
})?
.take(64)
.collect::<Result<Vec<_>, _>>()?;
- let mut list = OBB::new()
- .with(NODELIST_DISPLAYSTYLE, NLSTYLE_GRID)
- .with(NODELIST_TITLE, "items");
+ let mut list = OBB::new().with(NODELIST_DISPLAYSTYLE, NLSTYLE_GRID);
let mut iterstate = Vec::new();
for (r, is) in rows {