use std::path::PathBuf;
use crate::stream::data_stream::DataStream;
use std::sync::{Arc, Mutex};
use tinyflow_api::functions::*;
use crate::runtime::chain_job::ChainJob;
type PendingInitialState = Vec<(String, String, Vec<u8>)>;
#[derive(Clone)]
pub struct StreamEnv {
pub(crate) default_parallelism: usize,
pub(crate) checkpoint_interval_ms: u64,
pub chain_job: Arc<Mutex<Option<ChainJob>>>,
pub(crate) state_work_dir: Option<PathBuf>,
pub(crate) enable_chain_state: bool,
pub(crate) pending_job_state: Arc<Mutex<PendingInitialState>>,
}
impl Default for StreamEnv {
fn default() -> Self {
Self::new()
}
}
impl StreamEnv {
pub fn new() -> Self {
Self {
default_parallelism: 1,
checkpoint_interval_ms: 0,
chain_job: Arc::new(Mutex::new(None)),
state_work_dir: None,
enable_chain_state: true,
pending_job_state: Arc::new(Mutex::new(Vec::new())),
}
}
pub fn set_state_work_dir(&mut self, path: impl Into<PathBuf>) {
self.state_work_dir = Some(path.into());
}
pub fn set_enable_chain_state(&mut self, enable: bool) {
self.enable_chain_state = enable;
}
pub fn add_initial_job_state(&self, namespace: &str, key: &str, value: &[u8]) {
self.pending_job_state.lock().unwrap().push((
namespace.to_string(),
key.to_string(),
value.to_vec(),
));
}
pub fn set_parallelism(&mut self, p: usize) {
self.default_parallelism = p;
}
pub fn set_checkpoint_interval(&mut self, ms: u64) {
self.checkpoint_interval_ms = ms;
}
pub async fn execute(self) -> tinyflow_api::error::StreamResult<()> {
crate::stream::chain_execute::execute(self).await
}
#[doc(hidden)]
pub fn test_enable_chain_state(&self) -> bool {
self.enable_chain_state
}
#[doc(hidden)]
pub fn test_chain_step_count(&self) -> usize {
self.chain_job
.lock()
.unwrap()
.as_ref()
.map(|j| j.steps.len())
.unwrap_or(0)
}
#[doc(hidden)]
pub fn test_chain_frozen(&self) -> bool {
self.chain_job
.lock()
.unwrap()
.as_ref()
.map(|j| j.frozen)
.unwrap_or(false)
}
#[doc(hidden)]
pub fn test_freeze_chain(&self) {
if let Some(job) = self.chain_job.lock().unwrap().as_mut() {
job.frozen = true;
}
}
pub fn add_source<T: Send + 'static, S: SourceFunction<T> + Clone + Send + 'static>(
&self,
source: S,
) -> DataStream<T> {
self.add_source_with_factory(move || source.clone())
}
pub fn add_source_with_factory<T: Send + 'static, S: SourceFunction<T> + Send + 'static>(
&self,
factory: impl Fn() -> S + Send + 'static,
) -> DataStream<T> {
let mut job_guard = self.chain_job.lock().unwrap();
if job_guard.is_some() {
panic!("StreamEnv supports only one ChainJob; add_source already called");
}
let par = self.default_parallelism.max(1);
let factory = std::sync::Arc::new(std::sync::Mutex::new(factory));
let chain_factory =
crate::runtime::chain_segment::source_chain_factory(std::sync::Arc::clone(&factory));
let mut job = ChainJob::new(par);
job.push_step_with_types(
crate::runtime::chain_job::ChainStep {
kind: crate::runtime::chain_job::ChainOperatorKind::Source,
user_name: None,
factory: chain_factory,
},
None,
std::any::TypeId::of::<T>(),
);
*job_guard = Some(job);
DataStream::new(self.clone(), 0)
}
}