1use std::collections::HashMap;
7
8use serde::{Deserialize, Serialize};
9
10use crate::error::Result;
11use crate::DakeraClient;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct ClusterStatus {
20 pub cluster_id: String,
21 pub state: String,
22 pub node_count: u32,
23 pub total_vectors: u64,
24 pub namespace_count: u64,
25 pub version: String,
26 pub timestamp: u64,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct NodeInfo {
32 pub node_id: String,
33 pub address: String,
34 pub role: String,
35 pub status: String,
36 pub version: String,
37 pub uptime_seconds: u64,
38 pub vector_count: u64,
39 pub memory_bytes: u64,
40 #[serde(default)]
41 pub cpu_percent: f32,
42 #[serde(default)]
43 pub memory_percent: f32,
44 pub last_heartbeat: u64,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct NodeListResponse {
50 pub nodes: Vec<NodeInfo>,
51 pub total: u32,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct IndexStats {
61 pub index_type: String,
62 pub is_built: bool,
63 pub size_bytes: u64,
64 pub indexed_vectors: u64,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub last_rebuild: Option<u64>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
71pub struct NamespaceAdminInfo {
72 pub name: String,
73 pub vector_count: u64,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub dimension: Option<usize>,
76 pub index_type: String,
77 pub storage_bytes: u64,
78 pub document_count: u64,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub created_at: Option<u64>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub updated_at: Option<u64>,
83 pub index_stats: IndexStats,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct NamespaceListResponse {
89 pub namespaces: Vec<NamespaceAdminInfo>,
90 pub total: u64,
91 pub total_vectors: u64,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct OptimizeRequest {
97 #[serde(default)]
98 pub force: bool,
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub target_index_type: Option<String>,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct OptimizeResponse {
106 pub success: bool,
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub job_id: Option<String>,
109 pub message: String,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct IndexStatsResponse {
119 pub namespaces: HashMap<String, IndexStats>,
120 pub total_indexed_vectors: u64,
121 pub total_size_bytes: u64,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct RebuildIndexRequest {
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub namespace: Option<String>,
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub index_type: Option<String>,
131 #[serde(default)]
132 pub force: bool,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct RebuildIndexResponse {
138 pub success: bool,
139 pub job_id: String,
140 pub message: String,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct CacheStats {
150 pub enabled: bool,
151 pub cache_type: String,
152 pub entries: u64,
153 pub size_bytes: u64,
154 pub hits: u64,
155 pub misses: u64,
156 pub hit_rate: f64,
157 pub evictions: u64,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct ClearCacheRequest {
163 #[serde(skip_serializing_if = "Option::is_none")]
164 pub namespace: Option<String>,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct ClearCacheResponse {
170 pub success: bool,
171 pub entries_cleared: u64,
172 pub message: String,
173}
174
175#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct RuntimeConfig {
182 #[serde(skip_serializing_if = "Option::is_none")]
183 pub max_vectors_per_namespace: Option<u64>,
184 pub default_index_type: String,
185 pub cache_enabled: bool,
186 pub cache_max_size_bytes: u64,
187 pub rate_limit_enabled: bool,
188 pub rate_limit_rps: u32,
189 pub query_timeout_ms: u64,
190 #[serde(default = "default_true")]
192 pub autopilot_enabled: bool,
193 #[serde(default = "default_dedup_threshold")]
195 pub autopilot_dedup_threshold: f32,
196 #[serde(default = "default_dedup_interval")]
198 pub autopilot_dedup_interval_hours: u64,
199 #[serde(default = "default_consolidation_interval")]
201 pub autopilot_consolidation_interval_hours: u64,
202}
203
204fn default_true() -> bool {
205 true
206}
207fn default_dedup_threshold() -> f32 {
208 0.93
209}
210fn default_dedup_interval() -> u64 {
211 6
212}
213fn default_consolidation_interval() -> u64 {
214 12
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
219pub struct UpdateConfigResponse {
220 pub success: bool,
221 pub config: RuntimeConfig,
222 pub message: String,
223 #[serde(default, skip_serializing_if = "Vec::is_empty")]
224 pub warnings: Vec<String>,
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct QuotaConfig {
234 #[serde(skip_serializing_if = "Option::is_none")]
235 pub max_vectors: Option<u64>,
236 #[serde(skip_serializing_if = "Option::is_none")]
237 pub max_storage_bytes: Option<u64>,
238 #[serde(skip_serializing_if = "Option::is_none")]
239 pub max_queries_per_minute: Option<u64>,
240 #[serde(skip_serializing_if = "Option::is_none")]
241 pub max_writes_per_minute: Option<u64>,
242}
243
244#[derive(Debug, Clone, Serialize, Deserialize)]
246pub struct QuotaUsage {
247 #[serde(default)]
248 pub current_vectors: u64,
249 #[serde(default)]
250 pub current_storage_bytes: u64,
251 #[serde(default)]
252 pub queries_this_minute: u64,
253 #[serde(default)]
254 pub writes_this_minute: u64,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct QuotaStatus {
260 pub namespace: String,
261 pub config: QuotaConfig,
262 pub usage: QuotaUsage,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
267pub struct QuotaListResponse {
268 pub quotas: Vec<QuotaStatus>,
269 pub total: u64,
270 #[serde(skip_serializing_if = "Option::is_none")]
271 pub default_config: Option<QuotaConfig>,
272}
273
274#[derive(Debug, Clone, Serialize, Deserialize)]
280pub struct SlowQueryEntry {
281 pub id: String,
282 pub timestamp: u64,
283 pub namespace: String,
284 pub query_type: String,
285 pub duration_ms: f64,
286 #[serde(default)]
287 pub parameters: Option<serde_json::Value>,
288 #[serde(default)]
289 pub results_count: u64,
290 #[serde(default)]
291 pub vectors_scanned: u64,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
296pub struct SlowQueryListResponse {
297 pub queries: Vec<SlowQueryEntry>,
298 pub total: u64,
299 pub threshold_ms: f64,
300}
301
302#[derive(Debug, Clone, Serialize, Deserialize)]
308pub struct BackupInfo {
309 pub backup_id: String,
310 pub name: String,
311 pub backup_type: String,
312 pub status: String,
313 pub namespaces: Vec<String>,
314 pub vector_count: u64,
315 pub size_bytes: u64,
316 pub created_at: u64,
317 #[serde(skip_serializing_if = "Option::is_none")]
318 pub completed_at: Option<u64>,
319 #[serde(skip_serializing_if = "Option::is_none")]
320 pub duration_seconds: Option<u64>,
321 #[serde(skip_serializing_if = "Option::is_none")]
322 pub storage_path: Option<String>,
323 #[serde(skip_serializing_if = "Option::is_none")]
324 pub error: Option<String>,
325 pub encrypted: bool,
326 #[serde(skip_serializing_if = "Option::is_none")]
327 pub compression: Option<String>,
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct BackupListResponse {
333 pub backups: Vec<BackupInfo>,
334 pub total: u64,
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize)]
339pub struct CreateBackupRequest {
340 pub name: String,
341 #[serde(skip_serializing_if = "Option::is_none")]
342 pub backup_type: Option<String>,
343 #[serde(skip_serializing_if = "Option::is_none")]
344 pub namespaces: Option<Vec<String>>,
345 #[serde(skip_serializing_if = "Option::is_none")]
346 pub encrypt: Option<bool>,
347 #[serde(skip_serializing_if = "Option::is_none")]
348 pub compression: Option<String>,
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
353pub struct CreateBackupResponse {
354 pub backup: BackupInfo,
355 #[serde(skip_serializing_if = "Option::is_none")]
356 pub estimated_completion: Option<u64>,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct RestoreBackupRequest {
362 pub backup_id: String,
363 #[serde(skip_serializing_if = "Option::is_none")]
364 pub target_namespaces: Option<Vec<String>>,
365 #[serde(skip_serializing_if = "Option::is_none")]
366 pub overwrite: Option<bool>,
367 #[serde(skip_serializing_if = "Option::is_none")]
368 pub point_in_time: Option<u64>,
369}
370
371#[derive(Debug, Clone, Serialize, Deserialize)]
373pub struct RestoreBackupResponse {
374 pub restore_id: String,
375 pub status: String,
376 pub backup_id: String,
377 pub namespaces: Vec<String>,
378 pub started_at: u64,
379 #[serde(skip_serializing_if = "Option::is_none")]
380 pub estimated_completion: Option<u64>,
381 #[serde(skip_serializing_if = "Option::is_none")]
382 pub progress_percent: Option<u8>,
383 #[serde(skip_serializing_if = "Option::is_none")]
384 pub vectors_restored: Option<u64>,
385 #[serde(skip_serializing_if = "Option::is_none")]
386 pub completed_at: Option<u64>,
387 #[serde(skip_serializing_if = "Option::is_none")]
388 pub duration_seconds: Option<u64>,
389 #[serde(skip_serializing_if = "Option::is_none")]
390 pub error: Option<String>,
391}
392
393#[derive(Debug, Clone, Serialize, Deserialize)]
399pub struct AutoPilotConfig {
400 pub enabled: bool,
401 pub dedup_threshold: f32,
402 pub dedup_interval_hours: u64,
403 pub consolidation_interval_hours: u64,
404}
405
406#[derive(Debug, Clone, Serialize, Deserialize)]
408pub struct DedupResultSnapshot {
409 pub namespaces_processed: usize,
410 pub memories_scanned: usize,
411 pub duplicates_removed: usize,
412}
413
414#[derive(Debug, Clone, Serialize, Deserialize)]
416pub struct ConsolidationResultSnapshot {
417 pub namespaces_processed: usize,
418 pub memories_scanned: usize,
419 pub clusters_merged: usize,
420 pub memories_consolidated: usize,
421}
422
423#[derive(Debug, Clone, Serialize, Deserialize)]
425pub struct AutoPilotStatusResponse {
426 pub config: AutoPilotConfig,
427 #[serde(skip_serializing_if = "Option::is_none")]
428 pub last_dedup_at: Option<u64>,
429 #[serde(skip_serializing_if = "Option::is_none")]
430 pub last_consolidation_at: Option<u64>,
431 #[serde(skip_serializing_if = "Option::is_none")]
432 pub last_dedup: Option<DedupResultSnapshot>,
433 #[serde(skip_serializing_if = "Option::is_none")]
434 pub last_consolidation: Option<ConsolidationResultSnapshot>,
435 pub total_dedup_removed: u64,
436 pub total_consolidated: u64,
437}
438
439#[derive(Debug, Clone, Serialize, Deserialize, Default)]
441pub struct AutoPilotConfigRequest {
442 #[serde(skip_serializing_if = "Option::is_none")]
443 pub enabled: Option<bool>,
444 #[serde(skip_serializing_if = "Option::is_none")]
445 pub dedup_threshold: Option<f32>,
446 #[serde(skip_serializing_if = "Option::is_none")]
447 pub dedup_interval_hours: Option<u64>,
448 #[serde(skip_serializing_if = "Option::is_none")]
449 pub consolidation_interval_hours: Option<u64>,
450}
451
452#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct AutoPilotConfigResponse {
455 pub success: bool,
456 pub config: AutoPilotConfig,
457 pub message: String,
458}
459
460#[derive(Debug, Clone, Serialize, Deserialize)]
462#[serde(rename_all = "lowercase")]
463pub enum AutoPilotTriggerAction {
464 Dedup,
465 Consolidate,
466 All,
467}
468
469#[derive(Debug, Clone, Serialize, Deserialize)]
471pub struct AutoPilotTriggerRequest {
472 pub action: AutoPilotTriggerAction,
473}
474
475#[derive(Debug, Clone, Serialize, Deserialize)]
477pub struct AutoPilotDedupResult {
478 pub namespaces_processed: usize,
479 pub memories_scanned: usize,
480 pub duplicates_removed: usize,
481}
482
483#[derive(Debug, Clone, Serialize, Deserialize)]
485pub struct AutoPilotConsolidationResult {
486 pub namespaces_processed: usize,
487 pub memories_scanned: usize,
488 pub clusters_merged: usize,
489 pub memories_consolidated: usize,
490}
491
492#[derive(Debug, Clone, Serialize, Deserialize)]
494pub struct AutoPilotTriggerResponse {
495 pub success: bool,
496 pub action: AutoPilotTriggerAction,
497 #[serde(skip_serializing_if = "Option::is_none")]
498 pub dedup: Option<AutoPilotDedupResult>,
499 #[serde(skip_serializing_if = "Option::is_none")]
500 pub consolidation: Option<AutoPilotConsolidationResult>,
501 pub message: String,
502}
503
504#[derive(Debug, Clone, Serialize, Deserialize)]
510pub struct DecayConfigResponse {
511 pub strategy: String,
513 pub half_life_hours: f64,
515 pub min_importance: f32,
517}
518
519#[derive(Debug, Clone, Serialize, Deserialize, Default)]
521pub struct DecayConfigUpdateRequest {
522 #[serde(skip_serializing_if = "Option::is_none")]
524 pub strategy: Option<String>,
525 #[serde(skip_serializing_if = "Option::is_none")]
527 pub half_life_hours: Option<f64>,
528 #[serde(skip_serializing_if = "Option::is_none")]
530 pub min_importance: Option<f32>,
531}
532
533#[derive(Debug, Clone, Serialize, Deserialize)]
535pub struct DecayConfigUpdateResponse {
536 pub success: bool,
537 pub config: DecayConfigResponse,
538 pub message: String,
539}
540
541#[derive(Debug, Clone, Serialize, Deserialize)]
543pub struct LastDecayCycleStats {
544 pub namespaces_processed: usize,
545 pub memories_processed: usize,
546 pub memories_decayed: usize,
547 pub memories_deleted: usize,
548}
549
550#[derive(Debug, Clone, Serialize, Deserialize)]
552pub struct DecayStatsResponse {
553 pub total_decayed: u64,
555 pub total_deleted: u64,
557 #[serde(skip_serializing_if = "Option::is_none")]
559 pub last_run_at: Option<u64>,
560 pub cycles_run: u64,
562 #[serde(skip_serializing_if = "Option::is_none")]
564 pub last_cycle: Option<LastDecayCycleStats>,
565}
566
567#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct TtlCleanupRequest {
574 #[serde(skip_serializing_if = "Option::is_none")]
575 pub namespace: Option<String>,
576}
577
578#[derive(Debug, Clone, Serialize, Deserialize)]
580pub struct TtlCleanupResponse {
581 pub success: bool,
582 pub vectors_removed: u64,
583 pub namespaces_cleaned: Vec<String>,
584 pub message: String,
585}
586
587#[derive(Debug, Clone, Serialize, Deserialize)]
589pub struct TtlStats {
590 pub namespace: String,
591 pub vectors_with_ttl: u64,
592 pub expiring_within_hour: u64,
593 pub expiring_within_day: u64,
594 pub expired_pending_cleanup: u64,
595}
596
597#[derive(Debug, Clone, Serialize, Deserialize)]
599pub struct TtlStatsResponse {
600 pub namespaces: Vec<TtlStats>,
601 pub total_with_ttl: u64,
602 pub total_expired: u64,
603}
604
605impl DakeraClient {
610 pub async fn cluster_status(&self) -> Result<ClusterStatus> {
616 let url = format!("{}/admin/cluster/status", self.base_url);
617 let response = self.client.get(&url).send().await?;
618 self.handle_response(response).await
619 }
620
621 pub async fn cluster_nodes(&self) -> Result<NodeListResponse> {
623 let url = format!("{}/admin/cluster/nodes", self.base_url);
624 let response = self.client.get(&url).send().await?;
625 self.handle_response(response).await
626 }
627
628 pub async fn list_namespaces_admin(&self) -> Result<NamespaceListResponse> {
634 let url = format!("{}/admin/namespaces", self.base_url);
635 let response = self.client.get(&url).send().await?;
636 self.handle_response(response).await
637 }
638
639 pub async fn delete_namespace_admin(&self, namespace: &str) -> Result<serde_json::Value> {
641 let url = format!("{}/admin/namespaces/{}", self.base_url, namespace);
642 let response = self.client.delete(&url).send().await?;
643 self.handle_response(response).await
644 }
645
646 pub async fn optimize_namespace(
648 &self,
649 namespace: &str,
650 request: OptimizeRequest,
651 ) -> Result<OptimizeResponse> {
652 let url = format!("{}/admin/namespaces/{}/optimize", self.base_url, namespace);
653 let response = self.client.post(&url).json(&request).send().await?;
654 self.handle_response(response).await
655 }
656
657 pub async fn index_stats(&self) -> Result<IndexStatsResponse> {
663 let url = format!("{}/admin/indexes/stats", self.base_url);
664 let response = self.client.get(&url).send().await?;
665 self.handle_response(response).await
666 }
667
668 pub async fn rebuild_indexes(
670 &self,
671 request: RebuildIndexRequest,
672 ) -> Result<RebuildIndexResponse> {
673 let url = format!("{}/admin/indexes/rebuild", self.base_url);
674 let response = self.client.post(&url).json(&request).send().await?;
675 self.handle_response(response).await
676 }
677
678 pub async fn cache_stats(&self) -> Result<CacheStats> {
684 let url = format!("{}/admin/cache/stats", self.base_url);
685 let response = self.client.get(&url).send().await?;
686 self.handle_response(response).await
687 }
688
689 pub async fn cache_clear(&self, namespace: Option<&str>) -> Result<ClearCacheResponse> {
691 let url = format!("{}/admin/cache/clear", self.base_url);
692 let request = ClearCacheRequest {
693 namespace: namespace.map(|s| s.to_string()),
694 };
695 let response = self.client.post(&url).json(&request).send().await?;
696 self.handle_response(response).await
697 }
698
699 pub async fn get_config(&self) -> Result<RuntimeConfig> {
705 let url = format!("{}/admin/config", self.base_url);
706 let response = self.client.get(&url).send().await?;
707 self.handle_response(response).await
708 }
709
710 pub async fn update_config(
712 &self,
713 updates: HashMap<String, serde_json::Value>,
714 ) -> Result<UpdateConfigResponse> {
715 let url = format!("{}/admin/config", self.base_url);
716 let response = self.client.put(&url).json(&updates).send().await?;
717 self.handle_response(response).await
718 }
719
720 pub async fn get_quotas(&self) -> Result<QuotaListResponse> {
726 let url = format!("{}/admin/quotas", self.base_url);
727 let response = self.client.get(&url).send().await?;
728 self.handle_response(response).await
729 }
730
731 pub async fn get_quota(&self, namespace: &str) -> Result<QuotaStatus> {
733 let url = format!("{}/admin/quotas/{}", self.base_url, namespace);
734 let response = self.client.get(&url).send().await?;
735 self.handle_response(response).await
736 }
737
738 pub async fn set_quota(
740 &self,
741 namespace: &str,
742 config: QuotaConfig,
743 ) -> Result<serde_json::Value> {
744 let url = format!("{}/admin/quotas/{}", self.base_url, namespace);
745 let request = serde_json::json!({ "config": config });
746 let response = self.client.put(&url).json(&request).send().await?;
747 self.handle_response(response).await
748 }
749
750 pub async fn delete_quota(&self, namespace: &str) -> Result<serde_json::Value> {
752 let url = format!("{}/admin/quotas/{}", self.base_url, namespace);
753 let response = self.client.delete(&url).send().await?;
754 self.handle_response(response).await
755 }
756
757 pub async fn update_quotas(&self, config: Option<QuotaConfig>) -> Result<serde_json::Value> {
759 let url = format!("{}/admin/quotas/default", self.base_url);
760 let request = serde_json::json!({ "config": config });
761 let response = self.client.put(&url).json(&request).send().await?;
762 self.handle_response(response).await
763 }
764
765 pub async fn slow_queries(
771 &self,
772 limit: Option<usize>,
773 namespace: Option<&str>,
774 query_type: Option<&str>,
775 ) -> Result<SlowQueryListResponse> {
776 let mut url = format!("{}/admin/slow-queries", self.base_url);
777 let mut params = Vec::new();
778 if let Some(l) = limit {
779 params.push(format!("limit={}", l));
780 }
781 if let Some(ns) = namespace {
782 params.push(format!("namespace={}", ns));
783 }
784 if let Some(qt) = query_type {
785 params.push(format!("query_type={}", qt));
786 }
787 if !params.is_empty() {
788 url.push('?');
789 url.push_str(¶ms.join("&"));
790 }
791 let response = self.client.get(&url).send().await?;
792 self.handle_response(response).await
793 }
794
795 pub async fn slow_query_summary(&self) -> Result<serde_json::Value> {
797 let url = format!("{}/admin/slow-queries/summary", self.base_url);
798 let response = self.client.get(&url).send().await?;
799 self.handle_response(response).await
800 }
801
802 pub async fn clear_slow_queries(&self) -> Result<serde_json::Value> {
804 let url = format!("{}/admin/slow-queries", self.base_url);
805 let response = self.client.delete(&url).send().await?;
806 self.handle_response(response).await
807 }
808
809 pub async fn create_backup(
815 &self,
816 request: CreateBackupRequest,
817 ) -> Result<CreateBackupResponse> {
818 let url = format!("{}/admin/backups", self.base_url);
819 let response = self.client.post(&url).json(&request).send().await?;
820 self.handle_response(response).await
821 }
822
823 pub async fn list_backups(&self) -> Result<BackupListResponse> {
825 let url = format!("{}/admin/backups", self.base_url);
826 let response = self.client.get(&url).send().await?;
827 self.handle_response(response).await
828 }
829
830 pub async fn get_backup(&self, backup_id: &str) -> Result<BackupInfo> {
832 let url = format!("{}/admin/backups/{}", self.base_url, backup_id);
833 let response = self.client.get(&url).send().await?;
834 self.handle_response(response).await
835 }
836
837 pub async fn restore_backup(
839 &self,
840 request: RestoreBackupRequest,
841 ) -> Result<RestoreBackupResponse> {
842 let url = format!("{}/admin/backups/restore", self.base_url);
843 let response = self.client.post(&url).json(&request).send().await?;
844 self.handle_response(response).await
845 }
846
847 pub async fn delete_backup(&self, backup_id: &str) -> Result<serde_json::Value> {
849 let url = format!("{}/admin/backups/{}", self.base_url, backup_id);
850 let response = self.client.delete(&url).send().await?;
851 self.handle_response(response).await
852 }
853
854 pub async fn ttl_cleanup(&self, namespace: Option<&str>) -> Result<TtlCleanupResponse> {
860 let url = format!("{}/admin/ttl/cleanup", self.base_url);
861 let request = TtlCleanupRequest {
862 namespace: namespace.map(|s| s.to_string()),
863 };
864 let response = self.client.post(&url).json(&request).send().await?;
865 self.handle_response(response).await
866 }
867
868 pub async fn ttl_stats(&self) -> Result<TtlStatsResponse> {
870 let url = format!("{}/admin/ttl/stats", self.base_url);
871 let response = self.client.get(&url).send().await?;
872 self.handle_response(response).await
873 }
874
875 pub async fn autopilot_status(&self) -> Result<AutoPilotStatusResponse> {
881 let url = format!("{}/admin/autopilot/status", self.base_url);
882 let response = self.client.get(&url).send().await?;
883 self.handle_response(response).await
884 }
885
886 pub async fn autopilot_update_config(
890 &self,
891 request: AutoPilotConfigRequest,
892 ) -> Result<AutoPilotConfigResponse> {
893 let url = format!("{}/admin/autopilot/config", self.base_url);
894 let response = self.client.put(&url).json(&request).send().await?;
895 self.handle_response(response).await
896 }
897
898 pub async fn autopilot_trigger(
903 &self,
904 action: AutoPilotTriggerAction,
905 ) -> Result<AutoPilotTriggerResponse> {
906 let url = format!("{}/admin/autopilot/trigger", self.base_url);
907 let request = AutoPilotTriggerRequest { action };
908 let response = self.client.post(&url).json(&request).send().await?;
909 self.handle_response(response).await
910 }
911
912 pub async fn decay_config(&self) -> Result<DecayConfigResponse> {
921 let url = format!("{}/admin/decay/config", self.base_url);
922 let response = self.client.get(&url).send().await?;
923 self.handle_response(response).await
924 }
925
926 pub async fn decay_update_config(
932 &self,
933 request: DecayConfigUpdateRequest,
934 ) -> Result<DecayConfigUpdateResponse> {
935 let url = format!("{}/admin/decay/config", self.base_url);
936 let response = self.client.put(&url).json(&request).send().await?;
937 self.handle_response(response).await
938 }
939
940 pub async fn decay_stats(&self) -> Result<DecayStatsResponse> {
945 let url = format!("{}/admin/decay/stats", self.base_url);
946 let response = self.client.get(&url).send().await?;
947 self.handle_response(response).await
948 }
949}