1use std::sync::Arc;
2
3use tokio::sync::RwLock;
4
5use crate::types::PipePresetInfo;
6use crate::types::SinkInfo;
7
8pub struct ApiState {
9 pub sinks: Arc<RwLock<Vec<SinkConfig>>>,
10 pub pipes: Arc<RwLock<Vec<PipeConfigCache>>>,
11 pub pipe_presets: Arc<RwLock<Vec<PipePresetCache>>>,
12 pub db_client: Option<Arc<surrealdb::Surreal<surrealdb::engine::any::Any>>>,
13 pub lifecycle: Option<Arc<dyn LifecycleControl>>,
14 pub api_key: Option<String>,
15}
16
17#[async_trait::async_trait]
19pub trait LifecycleControl: Send + Sync {
20 async fn restart_with_config_json(
21 &self,
22 db: &surrealdb::Surreal<surrealdb::engine::any::Any>,
23 ) -> Result<(), oversync_core::error::OversyncError>;
24 async fn export_config(
25 &self,
26 db: &surrealdb::Surreal<surrealdb::engine::any::Any>,
27 format: crate::types::ExportConfigFormat,
28 ) -> Result<String, oversync_core::error::OversyncError>;
29 async fn import_config(
30 &self,
31 db: &surrealdb::Surreal<surrealdb::engine::any::Any>,
32 format: crate::types::ExportConfigFormat,
33 content: &str,
34 ) -> Result<Vec<String>, oversync_core::error::OversyncError>;
35 async fn pause(&self);
36 async fn resume(&self) -> Result<(), oversync_core::error::OversyncError>;
37 async fn is_running(&self) -> bool;
38 async fn is_paused(&self) -> bool;
39}
40
41pub struct SinkConfig {
42 pub name: String,
43 pub sink_type: String,
44 pub config: Option<serde_json::Value>,
45}
46
47pub struct PipeConfigCache {
48 pub name: String,
49 pub origin_connector: String,
50 pub origin_dsn: String,
51 pub targets: Vec<String>,
52 pub interval_secs: u64,
53 pub query_count: usize,
54 pub recipe: Option<serde_json::Value>,
55 pub enabled: bool,
56}
57
58pub struct PipePresetCache {
59 pub name: String,
60 pub description: Option<String>,
61 pub spec: serde_json::Value,
62}
63
64impl ApiState {
65 pub fn sinks_info(&self) -> Vec<SinkInfo> {
66 let sinks = match self.sinks.try_read() {
67 Ok(s) => s,
68 Err(_) => return vec![],
69 };
70 sinks
71 .iter()
72 .map(|s| SinkInfo {
73 name: s.name.clone(),
74 sink_type: s.sink_type.clone(),
75 config: s.config.clone(),
76 })
77 .collect()
78 }
79
80 pub fn pipes_info(&self) -> Vec<crate::types::PipeInfo> {
81 let pipes = match self.pipes.try_read() {
82 Ok(p) => p,
83 Err(_) => return vec![],
84 };
85 pipes
86 .iter()
87 .map(|p| crate::types::PipeInfo {
88 name: p.name.clone(),
89 origin_connector: p.origin_connector.clone(),
90 origin_dsn: p.origin_dsn.clone(),
91 targets: p.targets.clone(),
92 interval_secs: p.interval_secs,
93 query_count: p.query_count,
94 recipe: p.recipe.clone(),
95 enabled: p.enabled,
96 })
97 .collect()
98 }
99
100 pub fn pipe_presets_info(&self) -> Vec<PipePresetInfo> {
101 let presets = match self.pipe_presets.try_read() {
102 Ok(p) => p,
103 Err(_) => return vec![],
104 };
105 presets
106 .iter()
107 .map(|preset| PipePresetInfo {
108 name: preset.name.clone(),
109 description: preset.description.clone(),
110 spec: preset.spec.clone(),
111 })
112 .collect()
113 }
114}