mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
+1








14fba21e57
Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com> Signed-off-by: npub1jh9wn95s0472h86ahapupaf7m6kx4v9sx2n0atj2hltcfer8k06s5n3pyf <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Tyler Longwell <tlongwell@block.xyz> Signed-off-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub17jjz49l9jjmhhk7cac63j8yt9z555n9cw8vk7v5jz4vzw4ppld5qgj57cc <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Mari <95cae996907d7cab9f5dbf43c0f53edeac6ab0b032a6feae4abfd784e467b3f5@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Sami <f4a42a97e594b77bdbd8ee35191c8b28a94a4cb871d96f32921558275421fb68@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Quinn <96f056ad5f2305c8ddf637dc65d048aa4c12d7daeb8867690e34fca46b0ef64c@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co> Co-authored-by: Tyler Longwell <tlongwell@block.xyz> Co-authored-by: Sami <sami@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
55 lines
2.0 KiB
Rust
55 lines
2.0 KiB
Rust
#![deny(unsafe_code)]
|
|
#![warn(missing_docs)]
|
|
//! Buzz search — community-scoped Postgres full-text search over Buzz events.
|
|
//!
|
|
//! The index lives in the `events` table: `search_tsv TSVECTOR GENERATED
|
|
//! ALWAYS AS (to_tsvector('simple', content)) STORED`, with `GIN
|
|
//! (search_tsv)` as the access path. Because the column is `GENERATED ALWAYS`,
|
|
//! every row write *is* the index update — there is no separate indexer, no
|
|
//! mpsc queue, no reindex job, no consistency window to reason about. A
|
|
//! client cannot forge the tsvector out of sync with the content it signed.
|
|
//!
|
|
//! This crate is the **query** side. Indexing is the SQL row insert — owned
|
|
//! by `buzz-db`. The relay refetches canonical events through `buzz-db`'s
|
|
//! scoped fetcher and runs access checks per hit; search is never the access
|
|
//! boundary (conformance row 50).
|
|
//!
|
|
//! ## Multi-tenant fence
|
|
//!
|
|
//! Every [`SearchQuery`] carries a [`CommunityId`]. There is no construction
|
|
//! path through this crate that omits it, and every SQL execution binds
|
|
//! `community_id = $ctx` as the first predicate. A query bound to community
|
|
//! A cannot return events stored under community B, by construction.
|
|
|
|
/// Search error types.
|
|
pub mod error;
|
|
/// Search query execution.
|
|
pub mod query;
|
|
|
|
pub use buzz_core::CommunityId;
|
|
pub use error::SearchError;
|
|
pub use query::{search, ChannelScope, SearchHit, SearchMode, SearchQuery, SearchResult};
|
|
|
|
use sqlx::PgPool;
|
|
|
|
/// Thin handle around a `PgPool` for community-scoped FTS.
|
|
///
|
|
/// Holds nothing the pool itself doesn't already own. The whole purpose of
|
|
/// this type is a stable injection point for the relay's `AppState`.
|
|
#[derive(Debug, Clone)]
|
|
pub struct SearchService {
|
|
pool: PgPool,
|
|
}
|
|
|
|
impl SearchService {
|
|
/// Build a search service over an existing Postgres pool.
|
|
pub fn new(pool: PgPool) -> Self {
|
|
Self { pool }
|
|
}
|
|
|
|
/// Execute a community-scoped FTS query.
|
|
pub async fn search(&self, query: &SearchQuery) -> Result<SearchResult, SearchError> {
|
|
query::search(&self.pool, query).await
|
|
}
|
|
}
|