tinyflow_framework/env/
stream_env.rs1use std::path::PathBuf;
2
3use crate::stream::data_stream::DataStream;
4use std::sync::{Arc, Mutex};
5use tinyflow_api::functions::*;
6
7use crate::runtime::chain_job::ChainJob;
8
9type PendingInitialState = Vec<(String, String, Vec<u8>)>;
10
11#[derive(Clone)]
14pub struct StreamEnv {
15 pub(crate) default_parallelism: usize,
16 pub(crate) checkpoint_interval_ms: u64,
17 pub chain_job: Arc<Mutex<Option<ChainJob>>>,
18 pub(crate) state_work_dir: Option<PathBuf>,
20 pub(crate) enable_chain_state: bool,
23 pub(crate) pending_job_state: Arc<Mutex<PendingInitialState>>,
24}
25
26impl Default for StreamEnv {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32impl StreamEnv {
33 pub fn new() -> Self {
34 Self {
35 default_parallelism: 1,
36 checkpoint_interval_ms: 0,
37 chain_job: Arc::new(Mutex::new(None)),
38 state_work_dir: None,
39 enable_chain_state: true,
40 pending_job_state: Arc::new(Mutex::new(Vec::new())),
41 }
42 }
43
44 pub fn set_state_work_dir(&mut self, path: impl Into<PathBuf>) {
45 self.state_work_dir = Some(path.into());
46 }
47
48 pub fn set_enable_chain_state(&mut self, enable: bool) {
50 self.enable_chain_state = enable;
51 }
52
53 pub fn add_initial_job_state(&self, namespace: &str, key: &str, value: &[u8]) {
55 self.pending_job_state.lock().unwrap().push((
56 namespace.to_string(),
57 key.to_string(),
58 value.to_vec(),
59 ));
60 }
61
62 pub fn set_parallelism(&mut self, p: usize) {
63 self.default_parallelism = p;
64 }
65
66 pub fn set_checkpoint_interval(&mut self, ms: u64) {
67 self.checkpoint_interval_ms = ms;
68 }
69
70 pub async fn execute(self) -> tinyflow_api::error::StreamResult<()> {
72 crate::stream::chain_execute::execute(self).await
73 }
74
75 #[doc(hidden)]
77 pub fn test_enable_chain_state(&self) -> bool {
78 self.enable_chain_state
79 }
80
81 #[doc(hidden)]
83 pub fn test_chain_step_count(&self) -> usize {
84 self.chain_job
85 .lock()
86 .unwrap()
87 .as_ref()
88 .map(|j| j.steps.len())
89 .unwrap_or(0)
90 }
91
92 #[doc(hidden)]
93 pub fn test_chain_frozen(&self) -> bool {
94 self.chain_job
95 .lock()
96 .unwrap()
97 .as_ref()
98 .map(|j| j.frozen)
99 .unwrap_or(false)
100 }
101
102 #[doc(hidden)]
104 pub fn test_freeze_chain(&self) {
105 if let Some(job) = self.chain_job.lock().unwrap().as_mut() {
106 job.frozen = true;
107 }
108 }
109
110 pub fn add_source<T: Send + 'static, S: SourceFunction<T> + Clone + Send + 'static>(
111 &self,
112 source: S,
113 ) -> DataStream<T> {
114 self.add_source_with_factory(move || source.clone())
115 }
116
117 pub fn add_source_with_factory<T: Send + 'static, S: SourceFunction<T> + Send + 'static>(
118 &self,
119 factory: impl Fn() -> S + Send + 'static,
120 ) -> DataStream<T> {
121 let mut job_guard = self.chain_job.lock().unwrap();
122 if job_guard.is_some() {
123 panic!("StreamEnv supports only one ChainJob; add_source already called");
124 }
125 let par = self.default_parallelism.max(1);
126 let factory = std::sync::Arc::new(std::sync::Mutex::new(factory));
127 let chain_factory =
128 crate::runtime::chain_segment::source_chain_factory(std::sync::Arc::clone(&factory));
129 let mut job = ChainJob::new(par);
130 job.push_step_with_types(
131 crate::runtime::chain_job::ChainStep {
132 kind: crate::runtime::chain_job::ChainOperatorKind::Source,
133 user_name: None,
134 factory: chain_factory,
135 },
136 None,
137 std::any::TypeId::of::<T>(),
138 );
139 *job_guard = Some(job);
140 DataStream::new(self.clone(), 0)
141 }
142}