Skip to main content

khive_runtime/
note_read.rs

1//! Filtered note reads preserve the caller's visible scope and insertion cursor.
2
3use khive_storage::note::{Note, NoteFilter};
4use khive_storage::{PageRequest, SeekCursor};
5use uuid::Uuid;
6
7use crate::{KhiveRuntime, NamespaceToken, RuntimeError, RuntimeResult};
8
9impl KhiveRuntime {
10    pub async fn list_notes_filtered(
11        &self,
12        token: &NamespaceToken,
13        mut filter: NoteFilter,
14        limit: u32,
15        offset: u32,
16    ) -> RuntimeResult<Vec<Note>> {
17        filter.namespaces = token
18            .visible_namespace_strs()
19            .into_iter()
20            .map(str::to_owned)
21            .collect();
22        Ok(self
23            .notes(token)?
24            .query_notes_filtered_count_free(
25                token.namespace().as_str(),
26                &filter,
27                PageRequest {
28                    limit,
29                    offset: offset.into(),
30                },
31            )
32            .await?
33            .items)
34    }
35
36    pub async fn list_notes_filtered_after(
37        &self,
38        token: &NamespaceToken,
39        mut filter: NoteFilter,
40        after: Option<Uuid>,
41        limit: u32,
42    ) -> RuntimeResult<(Vec<Note>, Option<Uuid>)> {
43        let store = self.notes(token)?;
44        let after = match after {
45            None => None,
46            Some(id) => {
47                let note = self
48                    .get_note_including_deleted(token, id)
49                    .await?
50                    .ok_or_else(|| RuntimeError::NotFound(format!("note cursor {id}")))?;
51                Self::ensure_namespace_visible(&note.namespace, token)?;
52                let sequence = store.note_sequence(id).await?.ok_or_else(|| {
53                    RuntimeError::Internal(format!(
54                        "note cursor {id} has no insertion-sequence ledger row"
55                    ))
56                })?;
57                Some(SeekCursor { sequence, id })
58            }
59        };
60        filter.namespaces = token
61            .visible_namespace_strs()
62            .into_iter()
63            .map(str::to_owned)
64            .collect();
65        let page = store
66            .query_notes_filtered_after(token.namespace().as_str(), &filter, after, limit)
67            .await?;
68        Ok((page.items, page.next_after.map(|cursor| cursor.id)))
69    }
70}