pub trait NoteStore:
Send
+ Sync
+ 'static {
Show 26 methods
// Required methods
fn upsert_note<'life0, 'async_trait>(
&'life0 self,
note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn upsert_notes<'life0, 'async_trait>(
&'life0 self,
notes: Vec<Note>,
) -> Pin<Box<dyn Future<Output = StorageResult<BatchWriteSummary>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn get_note<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn get_note_including_deleted<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn delete_note<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
mode: DeleteMode,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn update_note_properties<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
properties: Option<Value>,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn set_note_property<'life0, 'life1, 'async_trait>(
&'life0 self,
id: Uuid,
key: &'life1 str,
value: Value,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn try_patch_note_property<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
id: Uuid,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
json_path: &'life3 str,
value: Value,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait;
fn query_notes<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
kind: Option<&'life2 str>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn query_notes_filtered<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn query_notes_filtered_bounded<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
max_rows: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn count_notes<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
kind: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn try_insert_note<'life0, 'async_trait>(
&'life0 self,
note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
// Provided methods
fn get_live_notes_by_key<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_key: &'life2 str,
_kind: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn query_keyed_notes<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_prefix: &'life3 str,
_after: Option<&'life4 NoteKeyCursor>,
_page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<(Vec<Note>, Option<NoteKeyCursor>)>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait { ... }
fn replace_note_if_unchanged<'life0, 'async_trait>(
&'life0 self,
_note: Note,
_expected_updated_at: i64,
_expected_deleted_at: Option<i64>,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn insert_note_if_absent<'life0, 'async_trait>(
&'life0 self,
_note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn patch_note_property_atomic<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_ids: Vec<Uuid>,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_json_path: &'life3 str,
_value: Value,
_updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn query_notes_count_free<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_kind: Option<&'life2 str>,
_page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn query_notes_filtered_count_free<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn count_notes_filtered_in_snapshot<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filters: &'life2 [NoteFilter],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<u64>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn count_notes_filtered_bounded_in_snapshot<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filters: &'life2 [NoteFilter],
_cap: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<BoundedCount>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn note_sequence<'life0, 'async_trait>(
&'life0 self,
_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<i64>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn query_notes_filtered_after<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_after: Option<SeekCursor>,
_limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<SeekPage<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn count_notes_in_namespaces<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
kind: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn get_notes_batch<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [Uuid],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
}Expand description
Temporal-referential note CRUD over the notes substrate table.
Required Methods§
Sourcefn upsert_note<'life0, 'async_trait>(
&'life0 self,
note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn upsert_note<'life0, 'async_trait>(
&'life0 self,
note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Insert or update a single note. Updates preserve the stored immutable key.
Sourcefn upsert_notes<'life0, 'async_trait>(
&'life0 self,
notes: Vec<Note>,
) -> Pin<Box<dyn Future<Output = StorageResult<BatchWriteSummary>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn upsert_notes<'life0, 'async_trait>(
&'life0 self,
notes: Vec<Note>,
) -> Pin<Box<dyn Future<Output = StorageResult<BatchWriteSummary>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Insert or update a batch of notes. Updates preserve each stored immutable key.
Sourcefn get_note<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_note<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Fetch a note by UUID, returning None if absent.
Sourcefn get_note_including_deleted<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn get_note_including_deleted<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Fetch a note by UUID regardless of soft-deletion state.
Returns the note row even when deleted_at is set. Callers use this
to distinguish “soft-deleted” from “never existed”.
Sourcefn delete_note<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
mode: DeleteMode,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn delete_note<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
mode: DeleteMode,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Delete a note by UUID using the specified delete mode.
Sourcefn update_note_properties<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
properties: Option<Value>,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn update_note_properties<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
properties: Option<Value>,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Patch properties/updated_at on an existing note in place via a real
UPDATE, leaving every other column (including the row’s rowid)
untouched.
Unlike upsert_note, which writes the complete note shape, this leaves
every non-property column untouched. It also never churns the row’s
implicit rowid, which is required by callers relying on stable row
identity (#780).
Returns true when a live (non-soft-deleted) row with this id was
found and updated, false otherwise.
Sourcefn set_note_property<'life0, 'life1, 'async_trait>(
&'life0 self,
id: Uuid,
key: &'life1 str,
value: Value,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn set_note_property<'life0, 'life1, 'async_trait>(
&'life0 self,
id: Uuid,
key: &'life1 str,
value: Value,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Atomically set one top-level key in a note’s JSON properties object.
The backend must perform the read/modify/write as one storage operation
so concurrent writes to different keys cannot overwrite each other.
value keeps its JSON type, including explicit JSON null. A SQL-NULL
property document is initialized as an empty object. A live row whose
stored document is a non-object is not modified and returns false, as
do missing and soft-deleted rows. Keys containing U+0000 must be
rejected: SQLite JSON-path labels cannot address them without risking
mutation of a shorter sibling key.
Sourcefn try_patch_note_property<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
id: Uuid,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
json_path: &'life3 str,
value: Value,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn try_patch_note_property<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
id: Uuid,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
json_path: &'life3 str,
value: Value,
updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Atomically patch a single properties JSON key on a note, but only
when the row’s current state (re-evaluated inside this same
statement, not a snapshot the caller fetched earlier) still satisfies
filter’s namespace/kind/property_filters.
Unlike set_note_property (which patches unconditionally once the row
is live) or update_note_properties (which replaces the whole
properties column with a value the caller already computed — safe
only when nothing else can have written to the row since the caller’s
read), this also rechecks filter against the row’s live state before
writing, so a target that stopped matching an eligibility predicate
between validation and this call is not mutated. Any other property
written concurrently between the caller’s read and this call survives
untouched either way. A live row whose stored properties document is
a non-object (scalar, array, or otherwise) is not modified and returns
false, mirroring set_note_property. Returns Ok(false) — not an
error — when no live row currently matches filter (id not found,
soft-deleted, an eligibility property changed since the caller last
validated it, or the stored document is not a JSON object); the
caller degrades that the same way as update_note_properties’s
Ok(false).
Sourcefn query_notes<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
kind: Option<&'life2 str>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_notes<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
kind: Option<&'life2 str>,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Query notes by namespace and optional kind with pagination. The returned total and page items must come from one consistent backend snapshot.
Sourcefn query_notes_filtered<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_notes_filtered<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Query notes with property-based filtering and custom sort. The returned total and page items must come from one consistent backend snapshot.
Sourcefn query_notes_filtered_bounded<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
max_rows: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_notes_filtered_bounded<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
filter: &'life2 NoteFilter,
max_rows: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Fetch up to max_rows + 1 notes matching filter in a single
deterministically-ordered SQL statement, with no separate COUNT(*)
and no pagination loop.
A single statement observes one consistent snapshot for its entire
execution, so the result cannot be split across a concurrent insert
the way a COUNT(*) followed by independent LIMIT/OFFSET pages
can. Callers detect the over-bound case by checking whether the
returned Vec has more than max_rows items — that means at least
max_rows + 1 rows matched and the caller must reject the query
rather than silently return a truncated, possibly priority-incomplete
set.
Sourcefn count_notes<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
kind: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn count_notes<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespace: &'life1 str,
kind: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Count notes in a namespace, optionally filtered by kind.
Sourcefn try_insert_note<'life0, 'async_trait>(
&'life0 self,
note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn try_insert_note<'life0, 'async_trait>(
&'life0 self,
note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Attempt to insert a note without overwriting an existing row.
Returns true when the row was newly written. Returns false only
when a live note with the same non-empty external_id already exists in
the same namespace and kind (confirmed dedup hit). Any other constraint
violation (e.g. a primary key collision) is surfaced as a StorageError
so that callers do not misinterpret unexpected failures as deduplication.
Provided Methods§
fn get_live_notes_by_key<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_key: &'life2 str,
_kind: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn query_keyed_notes<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_prefix: &'life3 str,
_after: Option<&'life4 NoteKeyCursor>,
_page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<(Vec<Note>, Option<NoteKeyCursor>)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
Sourcefn replace_note_if_unchanged<'life0, 'async_trait>(
&'life0 self,
_note: Note,
_expected_updated_at: i64,
_expected_deleted_at: Option<i64>,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn replace_note_if_unchanged<'life0, 'async_trait>(
&'life0 self,
_note: Note,
_expected_updated_at: i64,
_expected_deleted_at: Option<i64>,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Replace a note only when the persisted row still matches the caller’s read snapshot.
expected_updated_at is the snapshot revision and
expected_deleted_at closes the soft-delete race (legacy soft-delete
paths may change deleted_at without changing updated_at). The
replacement note’s updated_at must be strictly greater than that
persisted revision. Returns false when the row disappeared, changed,
or was supplied a non-advancing replacement revision. This is the
full-note compare-and-swap seam used when a pack hook derives coupled
fields from that snapshot before persistence. The default returns
Unsupported rather than falling back to an unguarded upsert and
reintroducing the stale-snapshot race.
Sourcefn insert_note_if_absent<'life0, 'async_trait>(
&'life0 self,
_note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn insert_note_if_absent<'life0, 'async_trait>(
&'life0 self,
_note: Note,
) -> Pin<Box<dyn Future<Output = StorageResult<bool>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Insert a note only if no row already holds its id, reporting whether this call is the one that inserted it.
This closes the other half of the read-modify-write race that
NoteStore::replace_note_if_unchanged closes. That one protects a
caller who read an existing row; this one protects a caller who read
no row. Where the id is derived rather than freshly generated — a
deterministic per-subject id — two callers can both read absence and
both write, and an upsert resolves that by overwriting, so the first
caller’s write is lost with no error on either side. Returns false
when a row already existed, which the caller maps to a conflict rather
than to success.
The pre-existing row is left exactly as it is: this must not be
implemented as an upsert, since overwriting is the behaviour being
avoided. The default returns Unsupported for that reason, rather
than falling back to upsert_note and silently reintroducing the
race under a name that promises otherwise.
Sourcefn patch_note_property_atomic<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_ids: Vec<Uuid>,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_json_path: &'life3 str,
_value: Value,
_updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn patch_note_property_atomic<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_ids: Vec<Uuid>,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_json_path: &'life3 str,
_value: Value,
_updated_at: i64,
) -> Pin<Box<dyn Future<Output = StorageResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Atomically patch one JSON property on every supplied note.
Each target is rechecked against namespace and filter inside the
same transaction. The operation commits only when every distinct id
matches exactly one live object-valued row; a missing, soft-deleted, or
no-longer-eligible target rolls the entire unit back. Other property
keys are preserved by the same storage-side json_set operation as
Self::try_patch_note_property. Backends without a transactional
multi-note implementation retain the default Unsupported result.
Sourcefn query_notes_count_free<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_kind: Option<&'life2 str>,
_page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_notes_count_free<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_kind: Option<&'life2 str>,
_page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Query notes by namespace and optional kind without computing an exact total.
Implementations must return total: None. Backends that cannot
guarantee a count-free projection must fail closed rather than invoke
Self::query_notes, whose exact total remains available to callers
that expose a snapshot-consistent count.
Sourcefn query_notes_filtered_count_free<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_notes_filtered_count_free<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_page: PageRequest,
) -> Pin<Box<dyn Future<Output = StorageResult<Page<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Query a filtered note page without computing an exact total.
Implementations must return total: None; callers that need a
has_more bit should request one lookahead row. Backends that cannot
guarantee a count-free projection must fail closed rather than invoke
Self::query_notes_filtered, whose exact total is intentionally
backlog-proportional.
Sourcefn count_notes_filtered_in_snapshot<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filters: &'life2 [NoteFilter],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<u64>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn count_notes_filtered_in_snapshot<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filters: &'life2 [NoteFilter],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<u64>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Count several filtered note populations in one consistent backend
snapshot. Backends that cannot provide that guarantee must return
crate::StorageError::Unsupported rather than composing independent
queries or treating an absent page total as zero. SQL backends should
override this operation so callers can retain separate index-friendly
predicates without racing between their counts.
Sourcefn count_notes_filtered_bounded_in_snapshot<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filters: &'life2 [NoteFilter],
_cap: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<BoundedCount>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn count_notes_filtered_bounded_in_snapshot<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filters: &'life2 [NoteFilter],
_cap: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<BoundedCount>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Count several filtered note populations in one backend snapshot, with
each count bounded by cap.
A saturated entry reports count == cap and saturated == true; an
unsaturated entry is exact. SQL implementations should count over a
limited SELECT 1 subquery so work is proportional to cap and the
caller’s own matching population, never an unrelated backlog. That
bound holds only when every property_filter in the given
NoteFilter is servable as an index key column (equality on a bound
parameter or a plan-time-provable partial-index predicate) all the way
down to the filter that actually narrows the population — a residual
filter evaluated after the index seek (a bound parameter the index
cannot use to skip rows) degrades the bound to work proportional to
the rows scanned before cap matches are found, not the rows that
match. Callers building filters against this bound must ensure the
full predicate set is indexed, not just the predicate that narrows the
population most. Backends that cannot preserve the shared snapshot or
work bound must fail closed.
Sourcefn note_sequence<'life0, 'async_trait>(
&'life0 self,
_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<i64>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn note_sequence<'life0, 'async_trait>(
&'life0 self,
_id: Uuid,
) -> Pin<Box<dyn Future<Output = StorageResult<Option<i64>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Resolve a note id to its immutable insertion sequence.
Sourcefn query_notes_filtered_after<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_after: Option<SeekCursor>,
_limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<SeekPage<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn query_notes_filtered_after<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_namespace: &'life1 str,
_filter: &'life2 NoteFilter,
_after: Option<SeekCursor>,
_limit: u32,
) -> Pin<Box<dyn Future<Output = StorageResult<SeekPage<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Query an immutable insertion-sequence keyset page with the same
predicates as Self::query_notes_filtered.
Sourcefn count_notes_in_namespaces<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
kind: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn count_notes_in_namespaces<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
namespaces: &'life1 [String],
kind: Option<&'life2 str>,
) -> Pin<Box<dyn Future<Output = StorageResult<u64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Count notes across the given namespaces, optionally filtered by kind.
The default preserves compatibility by summing the existing
single-namespace operation; SQL backends should override this with one
IN aggregate.
Sourcefn get_notes_batch<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [Uuid],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_notes_batch<'life0, 'life1, 'async_trait>(
&'life0 self,
ids: &'life1 [Uuid],
) -> Pin<Box<dyn Future<Output = StorageResult<Vec<Note>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Fetch multiple notes by UUID in a single call.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".