helios_persistence/search/writer.rs
1//! Search Index Writer Trait.
2//!
3//! Defines the interface for writing extracted search values to a backend's
4//! search index. Each backend implements this trait according to its storage model.
5
6use async_trait::async_trait;
7
8use crate::error::StorageResult;
9
10use super::extractor::ExtractedValue;
11
12/// Trait for writing search parameter values to an index.
13///
14/// This trait abstracts the storage of extracted search values, allowing
15/// different backends to implement their own indexing strategies.
16#[async_trait]
17pub trait SearchIndexWriter: Send + Sync {
18 /// Writes extracted values for a resource to the search index.
19 ///
20 /// This typically inserts multiple rows in a search_index table,
21 /// one for each extracted value.
22 ///
23 /// # Arguments
24 ///
25 /// * `tenant_id` - The tenant identifier
26 /// * `resource_type` - The resource type (e.g., "Patient")
27 /// * `resource_id` - The resource's logical ID
28 /// * `values` - The extracted search values to index
29 ///
30 /// # Returns
31 ///
32 /// The number of index entries created.
33 async fn write_entries(
34 &self,
35 tenant_id: &str,
36 resource_type: &str,
37 resource_id: &str,
38 values: Vec<ExtractedValue>,
39 ) -> StorageResult<usize>;
40
41 /// Deletes all search index entries for a resource.
42 ///
43 /// Called when a resource is updated (before re-indexing) or deleted.
44 ///
45 /// # Arguments
46 ///
47 /// * `tenant_id` - The tenant identifier
48 /// * `resource_type` - The resource type
49 /// * `resource_id` - The resource's logical ID
50 ///
51 /// # Returns
52 ///
53 /// The number of index entries deleted.
54 async fn delete_entries(
55 &self,
56 tenant_id: &str,
57 resource_type: &str,
58 resource_id: &str,
59 ) -> StorageResult<usize>;
60
61 /// Deletes all search index entries for a specific parameter.
62 ///
63 /// Used when a SearchParameter is deleted or disabled.
64 ///
65 /// # Arguments
66 ///
67 /// * `tenant_id` - The tenant identifier
68 /// * `param_url` - The SearchParameter's canonical URL
69 ///
70 /// # Returns
71 ///
72 /// The number of index entries deleted.
73 async fn delete_entries_for_param(
74 &self,
75 tenant_id: &str,
76 param_url: &str,
77 ) -> StorageResult<usize>;
78
79 /// Clears all search index entries for a tenant.
80 ///
81 /// Used during full reindexing or tenant cleanup.
82 ///
83 /// # Arguments
84 ///
85 /// * `tenant_id` - The tenant identifier
86 ///
87 /// # Returns
88 ///
89 /// The number of index entries deleted.
90 async fn clear_all(&self, tenant_id: &str) -> StorageResult<usize>;
91
92 /// Returns the number of index entries for a tenant.
93 ///
94 /// # Arguments
95 ///
96 /// * `tenant_id` - The tenant identifier
97 ///
98 /// # Returns
99 ///
100 /// The total number of index entries.
101 async fn count_entries(&self, tenant_id: &str) -> StorageResult<u64>;
102
103 /// Returns the number of index entries for a specific resource.
104 ///
105 /// # Arguments
106 ///
107 /// * `tenant_id` - The tenant identifier
108 /// * `resource_type` - The resource type
109 /// * `resource_id` - The resource's logical ID
110 ///
111 /// # Returns
112 ///
113 /// The number of index entries for this resource.
114 async fn count_resource_entries(
115 &self,
116 tenant_id: &str,
117 resource_type: &str,
118 resource_id: &str,
119 ) -> StorageResult<u64>;
120}
121
122/// Options for index writing operations.
123#[derive(Debug, Clone, Default)]
124pub struct WriteOptions {
125 /// Whether to replace existing entries (vs. append).
126 pub replace: bool,
127
128 /// Whether to skip validation (for bulk operations).
129 pub skip_validation: bool,
130
131 /// Batch size for bulk operations.
132 pub batch_size: Option<usize>,
133}
134
135impl WriteOptions {
136 /// Creates new write options.
137 pub fn new() -> Self {
138 Self::default()
139 }
140
141 /// Sets the replace flag.
142 pub fn replace(mut self) -> Self {
143 self.replace = true;
144 self
145 }
146
147 /// Sets the skip_validation flag.
148 pub fn skip_validation(mut self) -> Self {
149 self.skip_validation = true;
150 self
151 }
152
153 /// Sets the batch size.
154 pub fn with_batch_size(mut self, size: usize) -> Self {
155 self.batch_size = Some(size);
156 self
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 #[test]
165 fn test_write_options() {
166 let opts = WriteOptions::new().replace().with_batch_size(100);
167
168 assert!(opts.replace);
169 assert_eq!(opts.batch_size, Some(100));
170 }
171}