pub struct MessageService<'db> { /* private fields */ }Expand description
Canonical message search, explain, metadata, and context operations used by all adapters.
Implementations§
Source§impl<'db> MessageService<'db>
impl<'db> MessageService<'db>
pub const fn new( config: &'db Config, db: &'db Db, surface: SearchSurface, ) -> Self
Sourcepub fn message_search_spec(&self) -> Result<MessageSearchSpecification>
pub fn message_search_spec(&self) -> Result<MessageSearchSpecification>
Describe the final input catalogue and this service’s configured queryless/content defaults.
The configured overlay is resolved by Self::plan, not by a parallel documentation
algorithm. It performs no session scan or message query and retains only one small request.
Sourcepub fn search_legacy(
&self,
query: &str,
filters: &MessageFilters,
) -> Result<Vec<MessageHit>>
pub fn search_legacy( &self, query: &str, filters: &MessageFilters, ) -> Result<Vec<MessageHit>>
Search individual messages using the selected exact, fuzzy, or regex mode.
§Complexity
Let F be structurally filtered rows, C <= F safe-trigram candidates, B_F/B_C
their selected-field bytes, Q query length, P_Q total postings entries read for the
required grams, and K the requested page window. Schema-v4 content and tool-argument
literal/regex searches do O(Q + P_Q + C + B_C) work including authoritative
verification; worst case remains O(F + B_F) when no safe/selective anchor exists.
Tool-argument candidates come from raw JSON, then RFC 6901 projection remains authoritative.
Peak Rust result memory is O(K + bytes(K)) for finite non-fuzzy pages and O(F + B_F)
when limit == 0; SQLite’s implementation-owned statement/postings state is conservatively
O(P_Q + C). These paths are serial, so latency has the same critical-path bound as work.
Fuzzy search scores every filtered row with parallel batches, does
O(B_F + F + W log W) aggregate work for retained window W=offset+limit, and has ideal
scoring latency O(B_F/P + W log W) over P workers plus serial SQLite traversal and
scheduling overhead. Content and derived-field fuzzy paths both use bounded parallel
batches; tool-argument fuzzy projection remains exhaustive but parallelizes JSON parsing
and scoring. Peak Rust memory is O(W + bytes(W) + batch_budget + largest_row + P*Q);
validation rejects an unbounded fuzzy page.
pub fn plan(&self, request: MessageSearchRequest) -> Result<MessageSearchPlan>
Sourcepub fn search(
&self,
request: MessageSearchRequest,
) -> Result<MessageSearchResponse>
pub fn search( &self, request: MessageSearchRequest, ) -> Result<MessageSearchResponse>
Execute the canonical message-search request with surface-specific omitted-limit semantics.
With no explicit, purpose, or operation limit, Rust/CLI/Python preserve every literal, regex, or no-text match; MCP uses its configured finite page. Fuzzy search always requires a finite resolved page. Presentation limits are resolved separately and never affect hit membership. Planning, membership, evidence, includes, and context share one SQLite read snapshot, so a concurrent WAL refresh becomes visible only to a later search.
Sourcepub fn search_with_explain(
&self,
query: &str,
filters: &MessageFilters,
include_explain: bool,
) -> Result<(Vec<MessageHit>, Option<SearchExplain>)>
pub fn search_with_explain( &self, query: &str, filters: &MessageFilters, include_explain: bool, ) -> Result<(Vec<MessageHit>, Option<SearchExplain>)>
Run the same search as MessageService::search and optionally return its actual planner
receipt, including corpus size and any exact/regex prefilter decision.
Sourcepub fn session_metadata(
&self,
session_ids: &[String],
) -> Result<HashMap<String, SessionMeta>>
pub fn session_metadata( &self, session_ids: &[String], ) -> Result<HashMap<String, SessionMeta>>
Load compact metadata for the requested canonical IDs; absent IDs are omitted.
Sourcepub fn context(
&self,
session_id: &str,
seq: i64,
before: i64,
after: i64,
) -> Result<Vec<MessageHit>>
pub fn context( &self, session_id: &str, seq: i64, before: i64, after: i64, ) -> Result<Vec<MessageHit>>
Return a bounded sequence window around one message.
§Complexity
The (session_id, seq) index makes database work and memory proportional to
before + after + 1, subject to messages available in the session.
Sourcepub fn read_session(
&self,
filters: &MessageFilters,
order: MessageOrder,
) -> Result<Vec<MessageHit>>
pub fn read_session( &self, filters: &MessageFilters, order: MessageOrder, ) -> Result<Vec<MessageHit>>
Read one session’s messages, selecting the oldest or newest filters.limit by order,
always returned in chronological (seq-ascending) order. Wraps
Db::read_session_messages; filters.session_id must be set.
Trait Implementations§
Source§impl<'db> Clone for MessageService<'db>
impl<'db> Clone for MessageService<'db>
impl<'db> Copy for MessageService<'db>
Auto Trait Implementations§
impl<'db> !RefUnwindSafe for MessageService<'db>
impl<'db> !Send for MessageService<'db>
impl<'db> !Sync for MessageService<'db>
impl<'db> !UnwindSafe for MessageService<'db>
impl<'db> Freeze for MessageService<'db>
impl<'db> Unpin for MessageService<'db>
impl<'db> UnsafeUnpin for MessageService<'db>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more