Skip to main content

golem_ai_search/
lib.rs

1pub mod config;
2pub mod durability;
3pub mod error;
4pub mod model;
5pub mod wasi_compat;
6
7use crate::model::{
8    CreateIndexOptions, Doc, DocumentId, IndexName, Schema, SearchError, SearchHit, SearchQuery,
9    SearchResults, SearchStream,
10};
11use std::cell::RefCell;
12use std::str::FromStr;
13
14pub trait SearchStreamInterface: 'static {
15    fn as_any(&self) -> &dyn std::any::Any;
16    fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
17    fn get_next(&self) -> Option<Vec<SearchHit>>;
18    fn blocking_get_next(&self) -> Vec<SearchHit>;
19}
20
21pub trait SearchProvider {
22    type SearchStream: SearchStreamInterface;
23
24    /// Provider-specific configuration (API keys, base URLs, etc.) that the
25    /// caller resolves once and passes in. Each provider crate defines its
26    /// own concrete config type; see e.g.
27    /// `golem_ai_search_algolia::AlgoliaConfig`.
28    type ProviderConfig: Clone + 'static;
29
30    fn create_index(
31        provider_config: Self::ProviderConfig,
32        options: CreateIndexOptions,
33    ) -> Result<(), SearchError>;
34    fn delete_index(
35        provider_config: Self::ProviderConfig,
36        name: IndexName,
37    ) -> Result<(), SearchError>;
38    fn list_indexes(provider_config: Self::ProviderConfig) -> Result<Vec<IndexName>, SearchError>;
39    fn upsert(
40        provider_config: Self::ProviderConfig,
41        index: IndexName,
42        doc: Doc,
43    ) -> Result<(), SearchError>;
44    fn upsert_many(
45        provider_config: Self::ProviderConfig,
46        index: IndexName,
47        docs: Vec<Doc>,
48    ) -> Result<(), SearchError>;
49    fn delete(
50        provider_config: Self::ProviderConfig,
51        index: IndexName,
52        id: DocumentId,
53    ) -> Result<(), SearchError>;
54    fn delete_many(
55        provider_config: Self::ProviderConfig,
56        index: IndexName,
57        ids: Vec<DocumentId>,
58    ) -> Result<(), SearchError>;
59    fn get(
60        provider_config: Self::ProviderConfig,
61        index: IndexName,
62        id: DocumentId,
63    ) -> Result<Option<Doc>, SearchError>;
64    fn search(
65        provider_config: Self::ProviderConfig,
66        index: IndexName,
67        query: SearchQuery,
68    ) -> Result<SearchResults, SearchError>;
69    fn stream_search(
70        provider_config: Self::ProviderConfig,
71        index: IndexName,
72        query: SearchQuery,
73    ) -> Result<SearchStream, SearchError>;
74    fn get_schema(
75        provider_config: Self::ProviderConfig,
76        index: IndexName,
77    ) -> Result<Schema, SearchError>;
78    fn update_schema(
79        provider_config: Self::ProviderConfig,
80        index: IndexName,
81        schema: Schema,
82    ) -> Result<(), SearchError>;
83}
84
85impl<'a> From<&'a SearchError> for SearchError {
86    fn from(value: &'a SearchError) -> Self {
87        value.clone()
88    }
89}
90
91struct LoggingState {
92    logging_initialized: bool,
93}
94
95impl LoggingState {
96    fn init(&mut self) {
97        if !self.logging_initialized {
98            let _ = wasi_logger::Logger::install();
99            let max_level: log::LevelFilter = log::LevelFilter::from_str(
100                &std::env::var("SEARCH_PROVIDER_LOG_LEVEL").unwrap_or_default(),
101            )
102            .unwrap_or(log::LevelFilter::Info);
103            log::set_max_level(max_level);
104            self.logging_initialized = true;
105        }
106    }
107}
108
109thread_local! {
110    static LOGGING_STATE: RefCell<LoggingState> = const { RefCell::new(LoggingState {
111        logging_initialized: false,
112    }) };
113}
114
115pub fn init_logging() {
116    LOGGING_STATE.with_borrow_mut(|state| state.init());
117}