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 runtime_cache_snapshot(
25 &self,
26 ) -> Result<RuntimeCacheSnapshot, oversync_core::error::OversyncError>;
27 async fn export_config(
28 &self,
29 db: &surrealdb::Surreal<surrealdb::engine::any::Any>,
30 format: crate::types::ExportConfigFormat,
31 ) -> Result<String, oversync_core::error::OversyncError>;
32 async fn import_config(
33 &self,
34 db: &surrealdb::Surreal<surrealdb::engine::any::Any>,
35 format: crate::types::ExportConfigFormat,
36 content: &str,
37 ) -> Result<Vec<String>, oversync_core::error::OversyncError>;
38 async fn pause(&self);
39 async fn resume(&self) -> Result<(), oversync_core::error::OversyncError>;
40 async fn is_running(&self) -> bool;
41 async fn is_paused(&self) -> bool;
42}
43
44#[derive(Clone)]
45pub struct SinkConfig {
46 pub name: String,
47 pub sink_type: String,
48 pub config: Option<serde_json::Value>,
49}
50
51#[derive(Clone)]
52pub struct PipeConfigCache {
53 pub name: String,
54 pub origin_connector: String,
55 pub origin_dsn: String,
56 pub targets: Vec<String>,
57 pub interval_secs: u64,
58 pub query_count: usize,
59 pub recipe: Option<serde_json::Value>,
60 pub enabled: bool,
61}
62
63pub struct PipePresetCache {
64 pub name: String,
65 pub description: Option<String>,
66 pub spec: serde_json::Value,
67}
68
69#[derive(Default)]
70pub struct RuntimeCacheSnapshot {
71 pub sinks: Vec<SinkConfig>,
72 pub pipes: Vec<PipeConfigCache>,
73}
74
75impl ApiState {
76 pub fn sinks_info(&self) -> Vec<SinkInfo> {
77 let sinks = match self.sinks.try_read() {
78 Ok(s) => s,
79 Err(_) => return vec![],
80 };
81 sinks
82 .iter()
83 .map(|s| SinkInfo {
84 name: s.name.clone(),
85 sink_type: s.sink_type.clone(),
86 config: s.config.clone(),
87 })
88 .collect()
89 }
90
91 pub fn pipes_info(&self) -> Vec<crate::types::PipeInfo> {
92 let pipes = match self.pipes.try_read() {
93 Ok(p) => p,
94 Err(_) => return vec![],
95 };
96 pipes
97 .iter()
98 .map(|p| crate::types::PipeInfo {
99 name: p.name.clone(),
100 origin_connector: p.origin_connector.clone(),
101 origin_dsn: p.origin_dsn.clone(),
102 targets: p.targets.clone(),
103 interval_secs: p.interval_secs,
104 query_count: p.query_count,
105 recipe: p.recipe.clone(),
106 enabled: p.enabled,
107 })
108 .collect()
109 }
110
111 pub fn pipe_presets_info(&self) -> Vec<PipePresetInfo> {
112 let presets = match self.pipe_presets.try_read() {
113 Ok(p) => p,
114 Err(_) => return vec![],
115 };
116 presets
117 .iter()
118 .map(|preset| PipePresetInfo {
119 name: preset.name.clone(),
120 description: preset.description.clone(),
121 spec: preset.spec.clone(),
122 })
123 .collect()
124 }
125}