1use crate::convert::{cipher_blob_to_proto, create_version, key_to_proto, query_from_proto};
7use crate::error::{NetError, NetResult};
8use crate::proto::{aql, query};
9use crate::server_admin::{LogEntry, push_log_entry};
10use amaters_core::Query;
11use amaters_core::Update as UpdateOp;
12use amaters_core::traits::StorageEngine;
13use amaters_core::types::{CipherBlob, Key};
14use futures::StreamExt;
15use parking_lot::RwLock;
16use std::collections::VecDeque;
17use std::sync::Arc;
18use std::time::Instant;
19use tracing::{debug, error, info, warn};
20
21#[cfg(feature = "compute")]
22use crate::circuit_cache::{CircuitCache, CircuitCacheConfig};
23#[cfg(feature = "compute")]
24use amaters_core::compute::{FheExecutor, KeyManager, PredicateCompiler};
25#[cfg(feature = "compute")]
26use std::collections::HashMap;
27
28pub struct AqlServiceImpl<S: StorageEngine> {
32 storage: Arc<S>,
34 start_time: Instant,
36 recent_log: Arc<RwLock<VecDeque<LogEntry>>>,
38 #[cfg(feature = "compute")]
40 key_manager: Arc<KeyManager>,
41 #[cfg(feature = "compute")]
47 circuit_cache: CircuitCache,
48}
49
50impl<S: StorageEngine> AqlServiceImpl<S> {
51 #[cfg(feature = "compute")]
53 pub fn new(storage: Arc<S>) -> Self {
54 Self {
55 storage,
56 start_time: Instant::now(),
57 recent_log: Arc::new(RwLock::new(VecDeque::new())),
58 key_manager: Arc::new(KeyManager::new()),
59 circuit_cache: CircuitCache::new(CircuitCacheConfig::default()),
60 }
61 }
62
63 #[cfg(not(feature = "compute"))]
65 pub fn new(storage: Arc<S>) -> Self {
66 Self {
67 storage,
68 start_time: Instant::now(),
69 recent_log: Arc::new(RwLock::new(VecDeque::new())),
70 }
71 }
72
73 #[cfg(feature = "compute")]
75 pub fn with_key_manager(storage: Arc<S>, key_manager: Arc<KeyManager>) -> Self {
76 Self {
77 storage,
78 start_time: Instant::now(),
79 recent_log: Arc::new(RwLock::new(VecDeque::new())),
80 key_manager,
81 circuit_cache: CircuitCache::new(CircuitCacheConfig::default()),
82 }
83 }
84
85 pub async fn execute_query(&self, request: aql::QueryRequest) -> aql::QueryResponse {
87 let start_time = Instant::now();
88
89 info!(
90 "ExecuteQuery request received: request_id={:?}",
91 request.request_id
92 );
93
94 let proto_query = match request.query {
96 Some(q) => q,
97 None => {
98 let execution_time_ms = start_time.elapsed().as_millis() as u64;
99 return aql::QueryResponse {
100 response: Some(aql::query_response::Response::Error(
101 crate::proto::errors::ErrorResponse {
102 code: crate::proto::errors::ErrorCode::ErrorProtocolMissingField as i32,
103 message: "Missing query in request".to_string(),
104 category: crate::proto::errors::ErrorCategory::CategoryClientError
105 as i32,
106 details: None,
107 retry_after: None,
108 },
109 )),
110 request_id: request.request_id,
111 execution_time_ms,
112 };
113 }
114 };
115
116 let query = match query_from_proto(proto_query) {
117 Ok(q) => q,
118 Err(e) => {
119 error!("Failed to parse query: {}", e);
120 let execution_time_ms = start_time.elapsed().as_millis() as u64;
121 return aql::QueryResponse {
122 response: Some(aql::query_response::Response::Error(
123 crate::proto::errors::ErrorResponse {
124 code: e.error_code() as i32,
125 message: e.to_string(),
126 category: e.error_category() as i32,
127 details: None,
128 retry_after: None,
129 },
130 )),
131 request_id: request.request_id,
132 execution_time_ms,
133 };
134 }
135 };
136
137 let span = tracing::info_span!(
140 "amaters.execute_query",
141 "amaters.query.type" = query_type_name(&query),
142 "amaters.collection" = collection_name(&query),
143 "amaters.fhe" = uses_fhe(&query),
144 );
145
146 let result = {
148 use tracing::Instrument as _;
149 self.execute_query_internal(query).instrument(span).await
150 };
151
152 let execution_time_ms = start_time.elapsed().as_millis() as u64;
153
154 let response = match result {
156 Ok(query_result) => aql::QueryResponse {
157 response: Some(aql::query_response::Response::Result(query_result)),
158 request_id: request.request_id,
159 execution_time_ms,
160 },
161 Err(e) => {
162 error!("Query execution failed: {}", e);
163 push_log_entry(
164 &self.recent_log,
165 format!("ExecuteQuery elapsed={}ms error={}", execution_time_ms, e),
166 );
167 return aql::QueryResponse {
168 response: Some(aql::query_response::Response::Error(
169 crate::proto::errors::ErrorResponse {
170 code: e.error_code() as i32,
171 message: e.to_string(),
172 category: e.error_category() as i32,
173 details: None,
174 retry_after: None,
175 },
176 )),
177 request_id: request.request_id,
178 execution_time_ms,
179 };
180 }
181 };
182 push_log_entry(
183 &self.recent_log,
184 format!("ExecuteQuery elapsed={}ms ok", execution_time_ms),
185 );
186 response
187 }
188
189 #[doc(hidden)]
194 #[tracing::instrument(skip(self), fields(trace_id = tracing::field::Empty, duration_us = tracing::field::Empty))]
195 pub async fn execute_query_internal(&self, query: Query) -> NetResult<query::QueryResult> {
196 match query {
197 Query::Get { collection, key } => {
198 debug!(
199 "Executing GET query: collection={}, key={:?}",
200 collection, key
201 );
202
203 let key_str = key.to_string_lossy();
209 if let Some(admin_cmd) = key_str.strip_prefix("__admin__:") {
210 if let Some(json) = self.handle_admin_command(admin_cmd).await {
211 let blob = CipherBlob::new(json.into_bytes());
212 return Ok(query::QueryResult {
213 result: Some(query::query_result::Result::Single(
214 query::SingleResult {
215 value: Some(cipher_blob_to_proto(&blob)),
216 },
217 )),
218 });
219 }
220 return Ok(query::QueryResult {
222 result: Some(query::query_result::Result::Single(query::SingleResult {
223 value: None,
224 })),
225 });
226 }
227
228 let result = self.storage.get(&key).await?;
229
230 let result = match result {
231 Some(value) => query::QueryResult {
232 result: Some(query::query_result::Result::Single(query::SingleResult {
233 value: Some(cipher_blob_to_proto(&value)),
234 })),
235 },
236 None => query::QueryResult {
237 result: Some(query::query_result::Result::Single(query::SingleResult {
238 value: None,
239 })),
240 },
241 };
242
243 Ok(result)
244 }
245 Query::Set {
246 collection,
247 key,
248 value,
249 } => {
250 debug!(
251 "Executing SET query: collection={}, key={:?}",
252 collection, key
253 );
254
255 self.storage.put(&key, &value).await?;
256
257 Ok(query::QueryResult {
258 result: Some(query::query_result::Result::Success(query::SuccessResult {
259 affected_rows: 1,
260 })),
261 })
262 }
263 Query::Delete { collection, key } => {
264 debug!(
265 "Executing DELETE query: collection={}, key={:?}",
266 collection, key
267 );
268
269 self.storage.delete(&key).await?;
270
271 Ok(query::QueryResult {
272 result: Some(query::query_result::Result::Success(query::SuccessResult {
273 affected_rows: 1,
274 })),
275 })
276 }
277 Query::Range {
278 collection,
279 start,
280 end,
281 } => {
282 debug!(
283 "Executing RANGE query: collection={}, start={:?}, end={:?}",
284 collection, start, end
285 );
286
287 let results = self.storage.range(&start, &end).await?;
288
289 let values: Vec<query::KeyValue> = results
290 .into_iter()
291 .map(|(k, v)| query::KeyValue {
292 key: Some(key_to_proto(&k)),
293 value: Some(cipher_blob_to_proto(&v)),
294 encrypted_predicate_result: None,
295 })
296 .collect();
297
298 Ok(query::QueryResult {
299 result: Some(query::query_result::Result::Multi(query::MultiResult {
300 values,
301 })),
302 })
303 }
304 Query::Filter {
305 collection,
306 predicate,
307 } => {
308 #[cfg(not(feature = "compute"))]
309 {
310 let _ = (collection, predicate);
311 return Err(NetError::ServerInternal(
312 "FILTER queries require the compute feature".to_string(),
313 ));
314 }
315
316 #[cfg(feature = "compute")]
317 {
318 let min_key = Key::from_slice(&[]);
320 let max_key = Key::from_slice(&[0xFF; 256]);
321
322 let all_rows = match self.storage.range(&min_key, &max_key).await {
323 Ok(rows) => rows,
324 Err(e) => {
325 error!("Failed to retrieve rows for filter: {}", e);
326 return Err(NetError::from(e));
327 }
328 };
329
330 debug!("Filter: retrieved {} candidate rows", all_rows.len());
331
332 if all_rows.len() > 1000 {
333 warn!(
334 "Filter query retrieved {} rows, which may cause performance issues",
335 all_rows.len()
336 );
337 }
338
339 let first_is_plaintext = all_rows
344 .first()
345 .map(|(_, v)| predicate.evaluate_plaintext(v).is_some())
346 .unwrap_or(true); if first_is_plaintext {
349 info!(
350 "Executing FILTER query with server-side plaintext predicate evaluation"
351 );
352
353 let mut results = Vec::new();
354 let mut excluded: usize = 0;
355
356 for (key, value_blob) in all_rows {
357 match predicate.evaluate_plaintext(&value_blob) {
358 Some(true) => {
359 results.push(query::KeyValue {
360 key: Some(key_to_proto(&key)),
361 value: Some(cipher_blob_to_proto(&value_blob)),
362 encrypted_predicate_result: None,
363 });
364 }
365 Some(false) => {
366 excluded += 1;
368 }
369 None => {
370 warn!(
373 "Plaintext evaluation returned None for key {:?} mid-scan; \
374 including row conservatively",
375 key
376 );
377 results.push(query::KeyValue {
378 key: Some(key_to_proto(&key)),
379 value: Some(cipher_blob_to_proto(&value_blob)),
380 encrypted_predicate_result: None,
381 });
382 }
383 }
384 }
385
386 info!(
387 "FILTER query completed: {} rows matched, {} rows excluded by plaintext predicate",
388 results.len(),
389 excluded
390 );
391
392 return Ok(query::QueryResult {
393 result: Some(query::query_result::Result::Multi(query::MultiResult {
394 values: results,
395 })),
396 });
397 }
398
399 info!("Executing FILTER query with FHE predicate evaluation");
401
402 let circuit = match self.circuit_cache.get_or_compile(&predicate, || {
414 let mut compiler = PredicateCompiler::new();
415 compiler.compile(&predicate, amaters_core::compute::EncryptedType::U8)
418 }) {
419 Ok(c) => c,
420 Err(e) => {
421 error!("Failed to compile predicate: {}", e);
422 return Err(NetError::ServerInternal(format!(
423 "Predicate compilation failed: {}",
424 e
425 )));
426 }
427 };
428
429 debug!(
430 "Compiled predicate circuit: depth={}, gates={}",
431 circuit.depth, circuit.gate_count
432 );
433
434 let rhs = match PredicateCompiler::extract_rhs_value(&predicate) {
436 Ok(r) => r,
437 Err(e) => {
438 error!("Failed to extract RHS value: {}", e);
439 return Err(NetError::ServerInternal(format!(
440 "RHS extraction failed: {}",
441 e
442 )));
443 }
444 };
445
446 let executor = FheExecutor::new();
448
449 let mut results = Vec::new();
452 let mut execution_errors = 0;
453
454 for (key, value_blob) in all_rows {
455 let mut inputs = HashMap::new();
457 inputs.insert("value".to_string(), value_blob.clone());
458 inputs.insert("rhs".to_string(), rhs.clone());
459
460 match executor.execute(&circuit, &inputs) {
463 Ok(result_blob) => {
464 let result_bytes = result_blob.as_bytes().to_vec();
465
466 debug!(
467 "Executed predicate on key {:?}, result blob size: {}",
468 key,
469 result_bytes.len()
470 );
471
472 results.push(query::KeyValue {
473 key: Some(key_to_proto(&key)),
474 value: Some(cipher_blob_to_proto(&value_blob)),
475 encrypted_predicate_result: Some(result_bytes),
476 });
477 }
478 Err(e) => {
479 execution_errors += 1;
480 warn!("FHE execution failed for key {:?}: {}", key, e);
481 }
483 }
484 }
485
486 if execution_errors > 0 {
487 warn!(
488 "Filter query had {} FHE execution errors out of {} total rows",
489 execution_errors,
490 execution_errors + results.len()
491 );
492 }
493
494 info!(
495 "FILTER query completed, processed {} rows successfully",
496 results.len()
497 );
498
499 Ok(query::QueryResult {
500 result: Some(query::query_result::Result::Multi(query::MultiResult {
501 values: results,
502 })),
503 })
504 }
505 }
506 Query::Update {
507 collection,
508 predicate,
509 updates,
510 } => {
511 debug!(
512 "Executing UPDATE query: collection={}, updates_count={}",
513 collection,
514 updates.len()
515 );
516
517 #[cfg(feature = "compute")]
518 {
519 let circuit = match self.circuit_cache.get_or_compile(&predicate, || {
524 let mut compiler = PredicateCompiler::new();
525 compiler.compile(&predicate, amaters_core::compute::EncryptedType::U8)
526 }) {
527 Ok(c) => c,
528 Err(e) => {
529 error!("Failed to compile update predicate: {}", e);
530 return Err(NetError::ServerInternal(format!(
531 "Update predicate compilation failed: {}",
532 e
533 )));
534 }
535 };
536
537 let rhs = match PredicateCompiler::extract_rhs_value(&predicate) {
538 Ok(r) => r,
539 Err(e) => {
540 error!("Failed to extract RHS value for update predicate: {}", e);
541 return Err(NetError::ServerInternal(format!(
542 "Update RHS extraction failed: {}",
543 e
544 )));
545 }
546 };
547
548 let executor = FheExecutor::new();
549
550 let min_key = Key::from_slice(&[]);
552 let max_key = Key::from_slice(&[0xFF; 256]);
553 let all_rows = self.storage.range(&min_key, &max_key).await?;
554
555 let mut affected_rows: u64 = 0;
556
557 for (key, value_blob) in &all_rows {
558 let mut inputs = HashMap::new();
560 inputs.insert("value".to_string(), value_blob.clone());
561 inputs.insert("rhs".to_string(), rhs.clone());
562
563 let matches = match executor.execute(&circuit, &inputs) {
565 Ok(result_blob) => {
566 result_blob.as_bytes().iter().any(|&b| b != 0)
568 }
569 Err(e) => {
570 warn!("FHE predicate evaluation failed for key {:?}: {}", key, e);
571 continue;
572 }
573 };
574
575 if !matches {
576 continue;
577 }
578
579 let mut current_value = value_blob.clone();
581 for update_op in &updates {
582 current_value = apply_update_operation(¤t_value, update_op);
583 }
584
585 self.storage.put(key, ¤t_value).await?;
586 affected_rows += 1;
587 }
588
589 info!(
590 "UPDATE query completed: {} rows affected out of {} total",
591 affected_rows,
592 all_rows.len()
593 );
594
595 Ok(query::QueryResult {
596 result: Some(query::query_result::Result::Success(query::SuccessResult {
597 affected_rows,
598 })),
599 })
600 }
601
602 #[cfg(not(feature = "compute"))]
603 {
604 let _ = predicate;
608
609 let all_keys = self.storage.keys().await?;
610
611 if all_keys.is_empty() {
612 info!(
613 "UPDATE query on collection '{}': no keys found, 0 rows affected",
614 collection
615 );
616 return Ok(query::QueryResult {
617 result: Some(query::query_result::Result::Success(
618 query::SuccessResult { affected_rows: 0 },
619 )),
620 });
621 }
622
623 let mut affected_rows: u64 = 0;
624
625 for key in &all_keys {
626 let value_opt = self.storage.get(key).await?;
627 let current_value = match value_opt {
628 Some(v) => v,
629 None => continue,
630 };
631
632 let mut updated_value = current_value;
633 for update_op in &updates {
634 updated_value = apply_update_operation(&updated_value, update_op);
635 }
636
637 self.storage.put(key, &updated_value).await?;
638 affected_rows += 1;
639 }
640
641 info!(
642 "UPDATE query completed: {} rows affected in collection '{}'",
643 affected_rows, collection
644 );
645
646 Ok(query::QueryResult {
647 result: Some(query::query_result::Result::Success(query::SuccessResult {
648 affected_rows,
649 })),
650 })
651 }
652 }
653 Query::Join { .. } => Err(NetError::ServerInternal(
654 "Join queries are not yet supported server-side".to_string(),
655 )),
656 }
657 }
658
659 #[tracing::instrument(skip(self, request), fields(trace_id = tracing::field::Empty, query_count = request.queries.len(), duration_us = tracing::field::Empty))]
666 pub async fn execute_batch(&self, request: aql::BatchRequest) -> aql::BatchResponse {
667 let start_time = Instant::now();
668
669 info!(
670 "ExecuteBatch request received: request_id={:?}, query_count={}",
671 request.request_id,
672 request.queries.len()
673 );
674
675 if request.queries.is_empty() {
677 let execution_time_ms = start_time.elapsed().as_millis() as u64;
678 return aql::BatchResponse {
679 response: Some(aql::batch_response::Response::Results(aql::BatchResult {
680 results: Vec::new(),
681 })),
682 request_id: request.request_id,
683 execution_time_ms,
684 };
685 }
686
687 let mut results = Vec::with_capacity(request.queries.len());
688 let mut rollback_ops: Vec<RollbackOp> = Vec::new();
689
690 for (idx, proto_query) in request.queries.into_iter().enumerate() {
691 let core_query = match query_from_proto(proto_query) {
693 Ok(q) => q,
694 Err(e) => {
695 error!("Failed to parse query {} in batch: {}", idx, e);
696 self.rollback_operations(&rollback_ops).await;
698 let execution_time_ms = start_time.elapsed().as_millis() as u64;
699 push_log_entry(
700 &self.recent_log,
701 format!(
702 "ExecuteBatch elapsed={}ms error=parse_query_{}: {}",
703 execution_time_ms, idx, e
704 ),
705 );
706 return aql::BatchResponse {
707 response: Some(aql::batch_response::Response::Error(
708 crate::proto::errors::ErrorResponse {
709 code: e.error_code() as i32,
710 message: format!("Query {} in batch failed to parse: {}", idx, e),
711 category: e.error_category() as i32,
712 details: None,
713 retry_after: None,
714 },
715 )),
716 request_id: request.request_id,
717 execution_time_ms,
718 };
719 }
720 };
721
722 let rollback_op = self.build_rollback_op(&core_query).await;
724
725 match self.execute_query_internal(core_query).await {
726 Ok(query_result) => {
727 if let Some(op) = rollback_op {
729 rollback_ops.push(op);
730 }
731 results.push(query_result);
732 }
733 Err(e) => {
734 error!("Query {} in batch failed: {}", idx, e);
735 self.rollback_operations(&rollback_ops).await;
737 let execution_time_ms = start_time.elapsed().as_millis() as u64;
738 push_log_entry(
739 &self.recent_log,
740 format!(
741 "ExecuteBatch elapsed={}ms error=query_{}: {}",
742 execution_time_ms, idx, e
743 ),
744 );
745 return aql::BatchResponse {
746 response: Some(aql::batch_response::Response::Error(
747 crate::proto::errors::ErrorResponse {
748 code: e.error_code() as i32,
749 message: format!("Query {} in batch failed: {}", idx, e),
750 category: e.error_category() as i32,
751 details: None,
752 retry_after: None,
753 },
754 )),
755 request_id: request.request_id,
756 execution_time_ms,
757 };
758 }
759 }
760 }
761
762 let execution_time_ms = start_time.elapsed().as_millis() as u64;
763 info!(
764 "ExecuteBatch completed successfully: {} queries in {}ms",
765 results.len(),
766 execution_time_ms
767 );
768 push_log_entry(
769 &self.recent_log,
770 format!(
771 "ExecuteBatch elapsed={}ms queries={} ok",
772 execution_time_ms,
773 results.len()
774 ),
775 );
776
777 aql::BatchResponse {
778 response: Some(aql::batch_response::Response::Results(aql::BatchResult {
779 results,
780 })),
781 request_id: request.request_id,
782 execution_time_ms,
783 }
784 }
785
786 async fn build_rollback_op(&self, query: &Query) -> Option<RollbackOp> {
793 match query {
794 Query::Set { key, .. } => {
795 let old_value = match self.storage.get(key).await {
797 Ok(v) => v,
798 Err(e) => {
799 warn!("Failed to read old value for rollback tracking: {}", e);
800 None
801 }
802 };
803 Some(RollbackOp::UndoSet {
804 key: key.clone(),
805 old_value,
806 })
807 }
808 Query::Delete { key, .. } => {
809 let old_value = match self.storage.get(key).await {
811 Ok(v) => v,
812 Err(e) => {
813 warn!("Failed to read value for rollback tracking: {}", e);
814 None
815 }
816 };
817 Some(RollbackOp::UndoDelete {
818 key: key.clone(),
819 old_value,
820 })
821 }
822 Query::Update { .. } => {
823 let keys = match self.storage.keys().await {
825 Ok(k) => k,
826 Err(e) => {
827 warn!("Failed to list keys for update rollback tracking: {}", e);
828 return Some(RollbackOp::UndoUpdate {
829 snapshots: Vec::new(),
830 });
831 }
832 };
833 let mut snapshots = Vec::with_capacity(keys.len());
834 for key in &keys {
835 let value = match self.storage.get(key).await {
836 Ok(v) => v,
837 Err(e) => {
838 warn!(
839 "Failed to read value for key {:?} during update rollback tracking: {}",
840 key, e
841 );
842 None
843 }
844 };
845 snapshots.push((key.clone(), value));
846 }
847 Some(RollbackOp::UndoUpdate { snapshots })
848 }
849 Query::Get { .. } | Query::Range { .. } | Query::Filter { .. } => None,
851 Query::Join { .. } => None,
853 }
854 }
855
856 async fn rollback_operations(&self, ops: &[RollbackOp]) {
861 if ops.is_empty() {
862 return;
863 }
864
865 warn!("Rolling back {} operations due to batch failure", ops.len());
866
867 for (idx, op) in ops.iter().rev().enumerate() {
868 match op {
869 RollbackOp::UndoSet { key, old_value } => {
870 match old_value {
871 Some(value) => {
872 if let Err(e) = self.storage.put(key, value).await {
874 error!(
875 "Rollback failed for UndoSet (restore) at index {}: {}",
876 idx, e
877 );
878 } else {
879 debug!("Rolled back Set: restored old value for key {:?}", key);
880 }
881 }
882 None => {
883 if let Err(e) = self.storage.delete(key).await {
885 error!(
886 "Rollback failed for UndoSet (delete) at index {}: {}",
887 idx, e
888 );
889 } else {
890 debug!("Rolled back Set: deleted new key {:?}", key);
891 }
892 }
893 }
894 }
895 RollbackOp::UndoDelete { key, old_value } => {
896 if let Some(value) = old_value {
897 if let Err(e) = self.storage.put(key, value).await {
899 error!("Rollback failed for UndoDelete at index {}: {}", idx, e);
900 } else {
901 debug!("Rolled back Delete: restored value for key {:?}", key);
902 }
903 }
904 }
907 RollbackOp::UndoUpdate { snapshots } => {
908 let current_keys = match self.storage.keys().await {
910 Ok(k) => k,
911 Err(e) => {
912 error!(
913 "Rollback failed for UndoUpdate at index {}: cannot list keys: {}",
914 idx, e
915 );
916 continue;
917 }
918 };
919
920 let snapshot_keys: std::collections::HashSet<&Key> =
922 snapshots.iter().map(|(k, _)| k).collect();
923
924 for key in ¤t_keys {
926 if !snapshot_keys.contains(key) {
927 if let Err(e) = self.storage.delete(key).await {
928 error!(
929 "Rollback failed for UndoUpdate (remove new key) at index {}: {}",
930 idx, e
931 );
932 } else {
933 debug!("Rolled back Update: removed new key {:?}", key);
934 }
935 }
936 }
937
938 for (key, old_value) in snapshots {
940 match old_value {
941 Some(value) => {
942 if let Err(e) = self.storage.put(key, value).await {
943 error!(
944 "Rollback failed for UndoUpdate (restore) at index {}: {}",
945 idx, e
946 );
947 } else {
948 debug!("Rolled back Update: restored value for key {:?}", key);
949 }
950 }
951 None => {
952 if let Err(e) = self.storage.delete(key).await {
954 error!(
955 "Rollback failed for UndoUpdate (delete) at index {}: {}",
956 idx, e
957 );
958 }
959 }
960 }
961 }
962 debug!("Rolled back Update operation at index {}", idx);
963 }
964 }
965 }
966
967 info!("Rollback completed");
968 }
969
970 pub fn execute_stream(
983 &self,
984 request: aql::QueryRequest,
985 config: StreamConfig,
986 ) -> futures::stream::BoxStream<'static, Result<aql::StreamResponse, NetError>> {
987 use futures::StreamExt;
988
989 let storage = self.storage.clone();
990 let recent_log = self.recent_log.clone();
991 let request_id = request.request_id.clone();
992
993 let stream = async_stream::stream! {
994 let start_time = Instant::now();
995
996 info!(
997 "ExecuteStream request received: request_id={:?}, chunk_size={}",
998 request_id, config.chunk_size
999 );
1000
1001 let proto_query = match request.query {
1003 Some(q) => q,
1004 None => {
1005 yield Err(NetError::MissingField("query".to_string()));
1006 return;
1007 }
1008 };
1009
1010 let core_query = match query_from_proto(proto_query) {
1011 Ok(q) => q,
1012 Err(e) => {
1013 error!("Failed to parse stream query: {}", e);
1014 yield Err(e);
1015 return;
1016 }
1017 };
1018
1019 let results = match core_query {
1021 Query::Range { collection, start, end } => {
1022 debug!(
1023 "Executing streaming RANGE query: collection={}, start={:?}, end={:?}",
1024 collection, start, end
1025 );
1026 match storage.range(&start, &end).await {
1027 Ok(rows) => rows,
1028 Err(e) => {
1029 error!("Storage range query failed: {}", e);
1030 yield Err(NetError::from(e));
1031 return;
1032 }
1033 }
1034 }
1035 Query::Get { collection, key } => {
1036 debug!(
1037 "Executing streaming GET query: collection={}, key={:?}",
1038 collection, key
1039 );
1040 match storage.get(&key).await {
1041 Ok(Some(value)) => vec![(key, value)],
1042 Ok(None) => Vec::new(),
1043 Err(e) => {
1044 error!("Storage get query failed: {}", e);
1045 yield Err(NetError::from(e));
1046 return;
1047 }
1048 }
1049 }
1050 _ => {
1051 yield Err(NetError::InvalidRequest(
1052 "Only Range and Get queries are supported for streaming".to_string(),
1053 ));
1054 return;
1055 }
1056 };
1057
1058 let results = if let Some(max) = config.max_results {
1060 if results.len() > max {
1061 results.into_iter().take(max).collect::<Vec<_>>()
1062 } else {
1063 results
1064 }
1065 } else {
1066 results
1067 };
1068
1069 let total_count = results.len();
1070
1071 if start_time.elapsed() > config.timeout {
1073 yield Err(NetError::Timeout(
1074 "Query execution exceeded timeout before streaming began".to_string(),
1075 ));
1076 return;
1077 }
1078
1079 let mut sequence: u64 = 0;
1081 let chunks_iter: Vec<Vec<(Key, CipherBlob)>> = results
1082 .chunks(config.chunk_size)
1083 .map(|c| c.to_vec())
1084 .collect();
1085 let total_chunks = chunks_iter.len();
1086
1087 for (chunk_idx, chunk) in chunks_iter.into_iter().enumerate() {
1088 if start_time.elapsed() > config.timeout {
1090 yield Err(NetError::Timeout(
1091 format!("Streaming timed out at chunk {}/{}", chunk_idx + 1, total_chunks)
1092 ));
1093 return;
1094 }
1095
1096 let has_more = chunk_idx + 1 < total_chunks;
1097 let values: Vec<query::KeyValue> = chunk
1098 .into_iter()
1099 .map(|(k, v)| query::KeyValue {
1100 key: Some(key_to_proto(&k)),
1101 value: Some(cipher_blob_to_proto(&v)),
1102 encrypted_predicate_result: None,
1103 })
1104 .collect();
1105
1106 yield Ok(aql::StreamResponse {
1107 chunk: Some(aql::stream_response::Chunk::Batch(aql::StreamBatch {
1108 values,
1109 has_more,
1110 })),
1111 sequence,
1112 });
1113
1114 sequence += 1;
1115 }
1116
1117 yield Ok(aql::StreamResponse {
1119 chunk: Some(aql::stream_response::Chunk::End(aql::StreamEnd {
1120 total_count: total_count as u64,
1121 })),
1122 sequence,
1123 });
1124
1125 let elapsed_ms = start_time.elapsed().as_millis() as u64;
1126 info!(
1127 "ExecuteStream completed: {} items in {} chunks, {}ms",
1128 total_count,
1129 total_chunks,
1130 elapsed_ms
1131 );
1132 push_log_entry(
1133 &recent_log,
1134 format!(
1135 "ExecuteStream elapsed={}ms items={} chunks={} ok",
1136 elapsed_ms, total_count, total_chunks
1137 ),
1138 );
1139 };
1140
1141 stream.boxed()
1142 }
1143
1144 #[tracing::instrument(skip(self, _request))]
1146 pub async fn health_check(
1147 &self,
1148 _request: aql::HealthCheckRequest,
1149 ) -> aql::HealthCheckResponse {
1150 debug!("HealthCheck request received");
1151 push_log_entry(&self.recent_log, "HealthCheck ok".to_string());
1152
1153 aql::HealthCheckResponse {
1154 status: aql::HealthStatus::HealthServing as i32,
1155 message: Some("Service is healthy".to_string()),
1156 }
1157 }
1158
1159 #[tracing::instrument(skip(self, _request))]
1161 pub async fn get_server_info(
1162 &self,
1163 _request: aql::ServerInfoRequest,
1164 ) -> aql::ServerInfoResponse {
1165 debug!("GetServerInfo request received");
1166 push_log_entry(&self.recent_log, "GetServerInfo ok".to_string());
1167
1168 let mut capabilities = vec![
1169 "query.get".to_string(),
1170 "query.set".to_string(),
1171 "query.delete".to_string(),
1172 "query.range".to_string(),
1173 "query.update".to_string(),
1174 ];
1175
1176 #[cfg(feature = "compute")]
1177 capabilities.push("query.filter".to_string());
1178
1179 aql::ServerInfoResponse {
1180 version: Some(create_version()),
1181 supported_versions: vec![create_version()],
1182 capabilities,
1183 uptime_seconds: self.start_time.elapsed().as_secs(),
1184 }
1185 }
1186
1187 async fn handle_admin_command(&self, cmd: &str) -> Option<String> {
1193 crate::server_admin::handle_admin_command(
1194 cmd,
1195 self.start_time.elapsed().as_secs(),
1196 &self.recent_log,
1197 &self.storage,
1198 )
1199 .await
1200 }
1201}
1202
1203fn query_type_name(query: &Query) -> &'static str {
1207 match query {
1208 Query::Get { .. } => "Get",
1209 Query::Set { .. } => "Set",
1210 Query::Delete { .. } => "Delete",
1211 Query::Range { .. } => "Range",
1212 Query::Filter { .. } => "Filter",
1213 Query::Update { .. } => "Update",
1214 Query::Join { .. } => "Join",
1215 }
1216}
1217
1218fn collection_name(query: &Query) -> &str {
1220 match query {
1221 Query::Get { collection, .. } => collection,
1222 Query::Set { collection, .. } => collection,
1223 Query::Delete { collection, .. } => collection,
1224 Query::Range { collection, .. } => collection,
1225 Query::Filter { collection, .. } => collection,
1226 Query::Update { collection, .. } => collection,
1227 Query::Join { .. } => "",
1228 }
1229}
1230
1231fn uses_fhe(query: &Query) -> bool {
1233 matches!(query, Query::Filter { .. } | Query::Update { .. })
1234}
1235
1236pub use crate::server_builder::AqlServerBuilder;
1239pub use crate::server_types::StreamConfig;
1240use crate::server_types::{RollbackOp, apply_update_operation};
1241
1242#[cfg(test)]
1243#[path = "server_tests.rs"]
1244mod tests;