diff --git a/All.sln b/All.sln index 0d8a575e7..af0c5dbd3 100644 --- a/All.sln +++ b/All.sln @@ -125,6 +125,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{92C02EAF-93FB-4A2C-A235-8541D893163C}" ProjectSection(SolutionItems) = preProject scripts\macos\generate_grpc_models.sh = scripts\macos\generate_grpc_models.sh + scripts\windows\generate_grpc_models.ps1 = scripts\windows\generate_grpc_models.ps1 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{2918C7E3-3FC8-48A5-ADDF-8358E888B40C}" diff --git a/Ficus/docker/run/Run.RustFicusBackend.Dockerfile b/Ficus/docker/run/Run.RustFicusBackend.Dockerfile index efd4daa6c..bf4d31c46 100644 --- a/Ficus/docker/run/Run.RustFicusBackend.Dockerfile +++ b/Ficus/docker/run/Run.RustFicusBackend.Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.92.0 as build +FROM rust:1.93.0 as build RUN apt update -y && apt upgrade -y RUN apt-get update -y diff --git a/Ficus/docker/tests/Tests.Rust.Dockerfile b/Ficus/docker/tests/Tests.Rust.Dockerfile index 602cd5f18..70287f3fe 100644 --- a/Ficus/docker/tests/Tests.Rust.Dockerfile +++ b/Ficus/docker/tests/Tests.Rust.Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.92.0 as build +FROM rust:1.93.0 as build RUN apt update -y && apt upgrade -y RUN apt-get update -y diff --git a/Ficus/src/python/infra/generate_models.py b/Ficus/src/python/infra/generate_models.py index 763909631..44331cf49 100644 --- a/Ficus/src/python/infra/generate_models.py +++ b/Ficus/src/python/infra/generate_models.py @@ -15,7 +15,11 @@ def generate_models(): os.mkdir(models_dir) - python = '/usr/local/bin/python3' + if os.name == 'nt': + python = 'python' + else: + python = '/usr/local/bin/python3' + os.popen(f'{python} -m pip install grpcio-tools').read() packages = [] diff --git a/Ficus/src/rust/ficus/src/event_log/xes/xes_event.rs b/Ficus/src/rust/ficus/src/event_log/xes/xes_event.rs index 6f9aa8d7e..c35900f10 100644 --- a/Ficus/src/rust/ficus/src/event_log/xes/xes_event.rs +++ b/Ficus/src/rust/ficus/src/event_log/xes/xes_event.rs @@ -9,23 +9,14 @@ use crate::{ }, }; use chrono::{DateTime, Utc}; -use std::{ - collections::HashMap, - fmt::{Debug, Formatter}, - sync::Arc, -}; +use std::{collections::HashMap, fmt::Debug, sync::Arc}; +#[derive(Debug)] pub struct XesEventImpl { event_base: EventBase, payload: Option, EventPayloadValue>>, } -impl Debug for XesEventImpl { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str(self.name_pointer()) - } -} - impl XesEventImpl { pub fn new_all_fields(name: Arc, timestamp: DateTime, payload: Option, EventPayloadValue>>) -> Self { Self { diff --git a/Ficus/src/rust/ficus/src/features/clustering/error.rs b/Ficus/src/rust/ficus/src/features/clustering/error.rs index 61a45cef7..413af1798 100644 --- a/Ficus/src/rust/ficus/src/features/clustering/error.rs +++ b/Ficus/src/rust/ficus/src/features/clustering/error.rs @@ -2,10 +2,10 @@ use crate::{ pipelines::errors::pipeline_errors::{PipelinePartExecutionError, RawPartExecutionError}, utils::dataset::dataset::LabeledDataset, }; -use std::fmt::Display; pub type ClusteringResult = Result; +#[derive(Debug)] pub enum ClusteringError { NoRepeatSet, FailedToCreateNdArray, @@ -14,21 +14,7 @@ pub enum ClusteringError { } impl From for PipelinePartExecutionError { - fn from(val: ClusteringError) -> Self { - PipelinePartExecutionError::Raw(RawPartExecutionError::new(val.to_string())) - } -} - -impl Display for ClusteringError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str( - match self { - Self::NoRepeatSet => "NoRepeatSet".to_owned(), - Self::FailedToCreateNdArray => "FailedToCreateNdArray".to_owned(), - Self::FailedToCalculateSilhouetteScore => "FailedToCalculateSilhouetteScore".to_owned(), - Self::RawError(message) => message.clone(), - } - .as_str(), - ) + fn from(err: ClusteringError) -> Self { + PipelinePartExecutionError::Raw(RawPartExecutionError::new(format!("{err:?}"))) } } diff --git a/Ficus/src/rust/ficus/src/features/discovery/alpha/alpha.rs b/Ficus/src/rust/ficus/src/features/discovery/alpha/alpha.rs index dbd9dba5f..6e8e9576b 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/alpha/alpha.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/alpha/alpha.rs @@ -68,11 +68,7 @@ fn add_one_length_loops(provider: &impl AlphaPlusRelationsProvider, original_log } } - let id = petri_net.add_transition(Transition::empty( - transition_name.to_owned(), - false, - Some(transition_name.to_owned()), - )); + let id = petri_net.add_transition(Transition::empty(transition_name.to_owned(), Some(transition_name.to_owned()))); let place_id = match petri_net.find_place_id_by_name(alpha_set.to_string().as_str()) { Some(found_place_id) => found_place_id, @@ -196,7 +192,7 @@ fn create_petri_net(info: &dyn EventLogInfo, alpha_sets: Vec<&AlphaSet>) -> Defa let mut petri_net = PetriNet::default(); let mut event_classes_to_transition_ids = HashMap::new(); for class in info.all_event_classes() { - let id = petri_net.add_transition(Transition::empty(class.to_owned(), false, Some(class.to_owned()))); + let id = petri_net.add_transition(Transition::empty(class.to_owned(), Some(class.to_owned()))); event_classes_to_transition_ids.insert(class.as_ref(), id); } diff --git a/Ficus/src/rust/ficus/src/features/discovery/alpha/alpha_plus_plus_nfc/alpha_plus_plus_nfc.rs b/Ficus/src/rust/ficus/src/features/discovery/alpha/alpha_plus_plus_nfc/alpha_plus_plus_nfc.rs index b44a1d193..80a0be905 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/alpha/alpha_plus_plus_nfc/alpha_plus_plus_nfc.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/alpha/alpha_plus_plus_nfc/alpha_plus_plus_nfc.rs @@ -195,7 +195,7 @@ pub fn discover_petri_net_alpha_plus_plus_nfc(log: &TLog) -> Def let mut resulting_net = DefaultPetriNet::default(); let mut transitions_to_ids = HashMap::new(); for transition in info.all_event_classes().iter().copied().chain(one_length_loop_transitions.iter()) { - let id = resulting_net.add_transition(Transition::empty((*transition).to_owned(), false, Some((*transition).to_owned()))); + let id = resulting_net.add_transition(Transition::empty((*transition).to_owned(), Some((*transition).to_owned()))); transitions_to_ids.insert(transition, id); } diff --git a/Ficus/src/rust/ficus/src/features/discovery/ecfg/adjustments.rs b/Ficus/src/rust/ficus/src/features/discovery/ecfg/adjustments.rs index 2e7df2c36..faa6a84ab 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/ecfg/adjustments.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/ecfg/adjustments.rs @@ -134,6 +134,7 @@ fn connect_added_merged_node_to_graph(nodes_ids: &NeededNodesIds, added_node: &u added_node, NodesConnectionData::new(None, start_node_edge_weight, None), ); + graph.connect_nodes( added_node, &nodes_ids.end_node, diff --git a/Ficus/src/rust/ficus/src/features/discovery/ecfg/mod.rs b/Ficus/src/rust/ficus/src/features/discovery/ecfg/mod.rs index fbe066916..4c90b818e 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/ecfg/mod.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/ecfg/mod.rs @@ -6,3 +6,4 @@ pub mod discovery_xes; pub mod log_prepare; pub mod models; pub mod root_sequence; +pub mod to_petri_net; diff --git a/Ficus/src/rust/ficus/src/features/discovery/ecfg/to_petri_net.rs b/Ficus/src/rust/ficus/src/features/discovery/ecfg/to_petri_net.rs new file mode 100644 index 000000000..a5373f0f2 --- /dev/null +++ b/Ficus/src/rust/ficus/src/features/discovery/ecfg/to_petri_net.rs @@ -0,0 +1,42 @@ +use crate::{ + features::discovery::petri_net::{petri_net::DefaultPetriNet, place::Place, transition::Transition}, + utils::graph::graph::DefaultGraph, +}; +use std::{collections::HashMap, sync::Arc}; + +pub fn convert_to_petri_net(graph: &DefaultGraph) -> Result { + if graph.all_nodes().is_empty() { + return Ok(Default::default()); + } + + let mut petri_net = DefaultPetriNet::default(); + + let mut next_place_id = 0; + let mut nodes_data = HashMap::new(); + + for node in graph.all_nodes() { + let name = Arc::clone(node.data.as_ref().expect("must have name for all transitions")); + let t_id = petri_net.add_transition(Transition::empty(name.clone(), Some(name.clone()))); + + let in_place = petri_net.add_place(Place::with_name(format!("{next_place_id}"))); + let out_place = petri_net.add_place(Place::with_name(format!("{}", next_place_id + 1))); + + petri_net.connect_place_to_transition(&in_place, &t_id, None); + petri_net.connect_transition_to_place(&t_id, &out_place, None); + + nodes_data.insert(node.id, (in_place, out_place)); + next_place_id += 2; + } + + for edge in graph.all_edges() { + let from_place = nodes_data[edge.from_node()].1; + let to_place = nodes_data[edge.to_node()].0; + + let s_t = petri_net.add_transition(Transition::silent()); + + petri_net.connect_place_to_transition(&from_place, &s_t, None); + petri_net.connect_transition_to_place(&s_t, &to_place, None); + } + + Ok(petri_net) +} diff --git a/Ficus/src/rust/ficus/src/features/discovery/heuristic/heuristic_miner.rs b/Ficus/src/rust/ficus/src/features/discovery/heuristic/heuristic_miner.rs index 8bbe9b72c..aa43d5a3d 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/heuristic/heuristic_miner.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/heuristic/heuristic_miner.rs @@ -46,7 +46,7 @@ pub fn discover_petri_net_heuristic( fn construct_heuristic_petri_net(provider: &HeuristicMinerRelationsProvider, petri_net: &mut DefaultPetriNet) { let mut classes_to_ids = HashMap::new(); for class in provider.log_info().all_event_classes() { - let id = petri_net.add_transition(Transition::empty(class.to_owned(), false, Some(class.to_owned()))); + let id = petri_net.add_transition(Transition::empty(class.to_owned(), Some(class.to_owned()))); classes_to_ids.insert(class.to_owned(), id); } @@ -92,8 +92,7 @@ fn construct_heuristic_petri_net(provider: &HeuristicMinerRelationsProvider, pet petri_net.connect_transition_to_place(classes_to_ids.get(first_class).unwrap(), &post_place_id, None); for group in ¶llel_groups { - let name = Arc::::from(format!("silent_start_{first_class}")); - let id = petri_net.add_transition(Transition::empty(name.to_owned(), true, Some(name.to_owned()))); + let id = petri_net.add_transition(Transition::silent()); petri_net.connect_place_to_transition(&post_place_id, &id, None); for el in group.set().iter() { @@ -103,7 +102,7 @@ fn construct_heuristic_petri_net(provider: &HeuristicMinerRelationsProvider, pet used.insert(*el); } - } + }; for follower in &followers { if !used.contains(follower) { diff --git a/Ficus/src/rust/ficus/src/features/discovery/petri_net/petri_net.rs b/Ficus/src/rust/ficus/src/features/discovery/petri_net/petri_net.rs index af5e1eb8b..1efeddd46 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/petri_net/petri_net.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/petri_net/petri_net.rs @@ -10,6 +10,11 @@ struct PlaceTransitions { outgoing_transitions: Vec, } +pub const EMPTY_PLACE_TRANSITIONS: &PlaceTransitions = &PlaceTransitions { + incoming_transitions: vec![], + outgoing_transitions: vec![], +}; + #[derive(Debug, Default)] pub struct PetriNet where @@ -50,10 +55,10 @@ where id } - pub fn connect_place_to_transition(&mut self, from_place_id: &u64, to_transition_index: &u64, arc_data: Option) { + pub fn connect_place_to_transition(&mut self, from_place_id: &u64, to_transition_id: &u64, arc_data: Option) { self .transitions - .get_mut(to_transition_index) + .get_mut(to_transition_id) .unwrap() .add_incoming_arc(from_place_id, arc_data); @@ -63,7 +68,7 @@ where .get_mut(from_place_id) .unwrap() .outgoing_transitions - .push(*to_transition_index); + .push(*to_transition_id); } fn init_places_transitions(&mut self, place_id: &u64) { @@ -160,7 +165,7 @@ where } fn get_place_transitions(&self, place_id: &u64) -> &PlaceTransitions { - self.places_to_transitions.get(place_id).unwrap() + self.places_to_transitions.get(place_id).unwrap_or(EMPTY_PLACE_TRANSITIONS) } fn map_transitions(&self, ids: &[u64]) -> Vec<&Transition> { diff --git a/Ficus/src/rust/ficus/src/features/discovery/petri_net/pnml_serialization.rs b/Ficus/src/rust/ficus/src/features/discovery/petri_net/pnml_serialization.rs index e80b3874f..a65b1f5bc 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/petri_net/pnml_serialization.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/petri_net/pnml_serialization.rs @@ -2,6 +2,7 @@ use crate::{ features::discovery::petri_net::{arc::PetriNetArc, petri_net::PetriNet, place::Place, transition::Transition}, utils::xml_utils::{StartEndElementCookie, XmlWriteError}, }; +use log::trace; use quick_xml::{ Writer, events::{BytesText, Event}, @@ -16,6 +17,14 @@ const NET_TAG_NAME: &str = "net"; const TEXT_TAG_NAME: &str = "text"; const NAME_TAG_NAME: &str = "name"; +const TOOL_SPECIFIC_TAG_NAME: &str = "toolspecific"; +const TOOL_ATTR_NAME: &str = "tool"; +const PROM_VALUE: &str = "ProM"; +const VERSION_ATTR_NAME: &str = "version"; +const VERSION_VALUE: &str = "6.4"; +const ACTIVITY_ATTR_NAME: &str = "activity"; +const SILENT_ACTIVITY: &str = "$invisible$"; + const ID_ATTR_NAME: &str = "id"; const SOURCE_ATTR_NAME: &str = "source"; const TARGET_ATTR_NAME: &str = "target"; @@ -116,6 +125,18 @@ where drop(name); } + if transition.is_silent() { + let _ = StartEndElementCookie::new_with_attrs( + writer, + TOOL_SPECIFIC_TAG_NAME, + &vec![ + (TOOL_ATTR_NAME, PROM_VALUE), + (VERSION_ATTR_NAME, VERSION_VALUE), + (ACTIVITY_ATTR_NAME, SILENT_ACTIVITY), + ], + ); + } + drop(cookie) } diff --git a/Ficus/src/rust/ficus/src/features/discovery/petri_net/transition.rs b/Ficus/src/rust/ficus/src/features/discovery/petri_net/transition.rs index 16a7d5afa..7cc1c5571 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/petri_net/transition.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/petri_net/transition.rs @@ -37,17 +37,32 @@ where } } +impl Transition, ()> { + pub fn silent() -> Self { + const NAME: &str = "tau"; + + Self { + id: next_id(), + name: Arc::from(NAME), + silent_transition: true, + incoming_arcs: vec![], + outgoing_arcs: vec![], + data: Some(Arc::from(NAME)), + } + } +} + impl Transition where TTransitionData: ToString, { - pub fn empty(name: Arc, silent_transition: bool, data: Option) -> Self { + pub fn empty(name: Arc, data: Option) -> Self { Self { id: next_id(), name, - silent_transition, - incoming_arcs: Vec::new(), - outgoing_arcs: Vec::new(), + silent_transition: false, + incoming_arcs: vec![], + outgoing_arcs: vec![], data, } } diff --git a/Ficus/src/rust/ficus/src/features/discovery/timeline/discovery.rs b/Ficus/src/rust/ficus/src/features/discovery/timeline/discovery.rs index 6284d0a5b..1fe81f126 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/timeline/discovery.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/timeline/discovery.rs @@ -15,7 +15,6 @@ use getset::{Getters, MutGetters}; use std::{ cell::RefCell, collections::HashMap, - error::Error, fmt::{Debug, Display, Formatter}, ops::Deref, rc::Rc, @@ -74,16 +73,11 @@ pub struct TraceThreadEvent { stamp: i64, } +#[derive(Debug)] pub enum LogThreadsDiagramError { NotSupportedEventStamp, } -impl Debug for LogThreadsDiagramError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - Display::fmt(self, f) - } -} - impl Display for LogThreadsDiagramError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { @@ -92,8 +86,6 @@ impl Display for LogThreadsDiagramError { } } -impl Error for LogThreadsDiagramError {} - impl From for PipelinePartExecutionError { fn from(val: LogThreadsDiagramError) -> Self { PipelinePartExecutionError::Raw(RawPartExecutionError::new(val.to_string())) diff --git a/Ficus/src/rust/ficus/src/features/discovery/timeline/software_data/extractors/core.rs b/Ficus/src/rust/ficus/src/features/discovery/timeline/software_data/extractors/core.rs index 927db07ec..ce7e99818 100644 --- a/Ficus/src/rust/ficus/src/features/discovery/timeline/software_data/extractors/core.rs +++ b/Ficus/src/rust/ficus/src/features/discovery/timeline/software_data/extractors/core.rs @@ -4,7 +4,6 @@ use crate::{ }; use std::{ cell::RefCell, - error::Error, fmt::{Debug, Display, Formatter}, rc::Rc, str::FromStr, @@ -28,8 +27,6 @@ impl Display for SoftwareDataExtractionError { } } -impl Error for SoftwareDataExtractionError {} - pub trait EventGroupSoftwareDataExtractor { fn extract(&self, software_data: &mut SoftwareData, event_group: &EventGroup) -> Result<(), SoftwareDataExtractionError> { let events = event_group diff --git a/Ficus/src/rust/ficus/src/pipelines/activities_parts.rs b/Ficus/src/rust/ficus/src/pipelines/activities_parts.rs index 7dfdb0728..8694e5ae0 100644 --- a/Ficus/src/rust/ficus/src/pipelines/activities_parts.rs +++ b/Ficus/src/rust/ficus/src/pipelines/activities_parts.rs @@ -34,7 +34,7 @@ use crate::{ NARROW_ACTIVITIES_KEY, PATH_KEY, PATTERNS_DISCOVERY_STRATEGY_KEY, PATTERNS_KEY, PATTERNS_KIND_KEY, PIPELINE_KEY, REGEX_KEY, REGEXES_KEY, REPEAT_SETS_KEY, TRACE_ACTIVITIES_KEY, UNDEF_ACTIVITY_HANDLING_STRATEGY_KEY, UNDERLYING_EVENTS_COUNT_KEY, }, - pipeline_parts::PipelineParts, + pipeline_parts::{PIPELINE_PARTS, PipelineParts}, }, utils::{ log_serialization_format::LogSerializationFormat, @@ -225,7 +225,7 @@ impl PipelineParts { let adjusting_mode = *Self::get_user_data(config, &ADJUSTING_MODE_KEY)?; let log = Self::get_user_data(old_context, &EVENT_LOG_KEY)?; - let mut new_context = PipelineContext::empty_from(old_context); + let mut new_context = PipelineContext::empty(); if adjusting_mode == AdjustingMode::FromUnattachedSubTraces { if let Ok(activities) = Self::get_user_data(old_context, &TRACE_ACTIVITIES_KEY) { @@ -243,9 +243,7 @@ impl PipelineParts { old_activities.push(new_activity.clone()); } - old_context - .pipeline_parts() - .unwrap() + PIPELINE_PARTS .create_add_unattached_events_part(config.clone()) .execute(old_context, infra)?; diff --git a/Ficus/src/rust/ficus/src/pipelines/context.rs b/Ficus/src/rust/ficus/src/pipelines/context.rs index 4decc5ca3..14d1d3640 100644 --- a/Ficus/src/rust/ficus/src/pipelines/context.rs +++ b/Ficus/src/rust/ficus/src/pipelines/context.rs @@ -1,17 +1,14 @@ -use crate::{ - pipelines::pipeline_parts::PipelineParts, - utils::{ - performance::performance_cookie::PerformanceLogger, - user_data::{ - keys::{DefaultKey, Key}, - user_data::{UserData, UserDataImpl}, - }, +use super::errors::pipeline_errors::PipelinePartExecutionError; +use crate::utils::{ + performance::performance_cookie::PerformanceLogger, + user_data::{ + keys::{DefaultKey, Key}, + user_data::{UserData, UserDataImpl}, }, }; +use getset::Getters; use std::{any::Any, sync::Arc}; -use super::errors::pipeline_errors::PipelinePartExecutionError; - pub trait LogMessageHandler: Send + Sync { fn handle(&self, message: &str) -> Result<(), PipelinePartExecutionError>; } @@ -41,29 +38,20 @@ impl PipelineInfrastructure { } } -#[derive(Clone, Default)] -pub struct PipelineContext<'a> { +#[derive(Clone, Getters)] +pub struct PipelineContext { user_data: UserDataImpl, - pipeline_parts: Option<&'a PipelineParts>, } -impl<'a> PipelineContext<'a> { - pub fn new_with_logging(parts: &'a PipelineParts) -> Self { - Self { - user_data: Default::default(), - pipeline_parts: Some(parts), - } - } - - pub fn empty_from(other: &'a PipelineContext) -> Self { +impl PipelineContext { + pub fn empty() -> Self { Self { user_data: Default::default(), - pipeline_parts: other.pipeline_parts, } } } -impl<'a> UserData for PipelineContext<'a> { +impl UserData for PipelineContext { fn len(&self) -> usize { self.user_data.len() } @@ -101,11 +89,7 @@ impl<'a> UserData for PipelineContext<'a> { } } -impl<'a> PipelineContext<'a> { - pub fn pipeline_parts(&self) -> Option<&PipelineParts> { - self.pipeline_parts - } - +impl PipelineContext { pub fn devastate_user_data(self) -> UserDataImpl { self.user_data } diff --git a/Ficus/src/rust/ficus/src/pipelines/errors/pipeline_errors.rs b/Ficus/src/rust/ficus/src/pipelines/errors/pipeline_errors.rs index 2f32a9190..dbcb3bfe5 100644 --- a/Ficus/src/rust/ficus/src/pipelines/errors/pipeline_errors.rs +++ b/Ficus/src/rust/ficus/src/pipelines/errors/pipeline_errors.rs @@ -1,7 +1,4 @@ -use std::{ - error::Error, - fmt::{Debug, Display, Formatter}, -}; +use std::fmt::{Debug, Display, Formatter}; #[derive(Debug)] pub enum PipelinePartExecutionError { @@ -28,6 +25,7 @@ impl PipelinePartExecutionError { } } +#[derive(Debug)] pub struct MissingContextError { context_key_name: String, } @@ -44,14 +42,7 @@ impl Display for MissingContextError { } } -impl Debug for MissingContextError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("MissingContextError") - .field("context_key_name", &self.context_key_name) - .finish() - } -} - +#[derive(Debug)] pub struct RawPartExecutionError { message: String, } @@ -62,16 +53,6 @@ impl Display for RawPartExecutionError { } } -impl Debug for RawPartExecutionError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("PipelinePartExecutionError") - .field("message", &self.message) - .finish() - } -} - -impl Error for RawPartExecutionError {} - impl RawPartExecutionError { pub fn new(message: String) -> Self { Self { message } diff --git a/Ficus/src/rust/ficus/src/pipelines/pipeline_parts.rs b/Ficus/src/rust/ficus/src/pipelines/pipeline_parts.rs index 40f199897..e7e1b3e0c 100644 --- a/Ficus/src/rust/ficus/src/pipelines/pipeline_parts.rs +++ b/Ficus/src/rust/ficus/src/pipelines/pipeline_parts.rs @@ -15,7 +15,7 @@ use crate::{ }; use derive_new::new; use fancy_regex::Regex; -use std::collections::HashMap; +use std::{cell::LazyCell, collections::HashMap}; pub struct PipelineParts { names_to_parts: HashMap, @@ -54,14 +54,10 @@ macro_rules! pipeline_part { }; } -impl Default for PipelineParts { - fn default() -> Self { - Self::new() - } -} +pub const PIPELINE_PARTS: LazyCell = LazyCell::new(|| PipelineParts::new()); impl PipelineParts { - pub fn new() -> Self { + fn new() -> Self { let parts = vec![ Self::read_log_from_xes(), Self::write_log_to_xes(), diff --git a/Ficus/src/rust/ficus/src/utils/silhouette.rs b/Ficus/src/rust/ficus/src/utils/silhouette.rs index 98dc47466..a8614c9c2 100644 --- a/Ficus/src/rust/ficus/src/utils/silhouette.rs +++ b/Ficus/src/rust/ficus/src/utils/silhouette.rs @@ -13,7 +13,7 @@ impl Display for SilhouetteScoreError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { SilhouetteScoreError::NotEnoughSamples => f.write_str("Not enough samples for silhouette score"), - &SilhouetteScoreError::InappropriateLabelsCount => f.write_str("Labels count should be 2 <= n_labels <= n_samples - 1"), + SilhouetteScoreError::InappropriateLabelsCount => f.write_str("Labels count should be 2 <= n_labels <= n_samples - 1"), } } } diff --git a/Ficus/src/rust/ficus/src/utils/xml_utils.rs b/Ficus/src/rust/ficus/src/utils/xml_utils.rs index eaf461f9b..b823ef60b 100644 --- a/Ficus/src/rust/ficus/src/utils/xml_utils.rs +++ b/Ficus/src/rust/ficus/src/utils/xml_utils.rs @@ -4,13 +4,13 @@ use quick_xml::{ }; use std::{ cell::RefCell, - error::Error, fmt::{Debug, Display}, io, string::FromUtf8Error, sync::Arc, }; +#[derive(Debug)] pub enum XmlWriteError { FromUt8Error(FromUtf8Error), IOError(io::Error), @@ -27,18 +27,6 @@ impl Display for XmlWriteError { } } -impl Debug for XmlWriteError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::FromUt8Error(arg0) => f.debug_tuple("FromUt8Error").field(arg0).finish(), - Self::IOError(arg0) => f.debug_tuple("IOError").field(arg0).finish(), - Self::WriterError(arg0) => f.debug_tuple("WriterError").field(arg0).finish(), - } - } -} - -impl Error for XmlWriteError {} - pub fn write_empty(writer: &mut Writer, tag_name: &str, attrs: &Vec<(&str, &str)>) -> Result<(), XmlWriteError> where T: std::io::Write, diff --git a/Ficus/src/rust/ficus/tests/discovery/ecfg_discovery.rs b/Ficus/src/rust/ficus/tests/discovery/ecfg_discovery.rs index cd2f0e748..d27b1f08d 100644 --- a/Ficus/src/rust/ficus/tests/discovery/ecfg_discovery.rs +++ b/Ficus/src/rust/ficus/tests/discovery/ecfg_discovery.rs @@ -1,11 +1,16 @@ +use crate::test_core::{gold_based_test::execute_test_with_gold, test_paths::get_serialized_petri_nets_gold_path}; use ficus::{ - features::discovery::ecfg::{ - context::DiscoveryContext, - discovery::discover_ecfg, - models::{EventWithUniqueId, RootSequenceKind}, - root_sequence::discover_root_sequence, + features::discovery::{ + ecfg::{ + context::DiscoveryContext, + discovery::discover_ecfg, + models::{EventWithUniqueId, RootSequenceKind}, + root_sequence::discover_root_sequence, + to_petri_net::convert_to_petri_net, + }, + petri_net::pnml_serialization::serialize_to_pnml, }, - utils::user_data::user_data::UserDataImpl, + utils::{graph::graph::DefaultGraph, user_data::user_data::UserDataImpl}, vecs, }; use std::sync::Arc; @@ -28,6 +33,14 @@ pub fn test_ecfg_1() { ); } +#[test] +pub fn test_ecfg_to_petri_net_1() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_1", + vec![vecs!["A", "B", "C", "D", "E"], vecs!["A", "B", "D", "E"]], + ); +} + #[test] pub fn test_ecfg_2() { execute_ecfg_discovery_test( @@ -47,6 +60,14 @@ pub fn test_ecfg_2() { ); } +#[test] +pub fn test_ecfg_to_petri_net_2() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_2", + vec![vecs!["A", "B", "C", "D", "E"], vecs!["A", "X", "Y", "E"]], + ); +} + #[test] pub fn test_ecfg_3() { execute_ecfg_discovery_test( @@ -67,16 +88,34 @@ pub fn test_ecfg_3() { ) } +#[test] +pub fn test_ecfg_to_petri_net_3() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_3", + vec![vecs!["A"], vecs!["B"], vecs!["C"], vecs!["D"], vecs!["E"]], + ); +} + #[test] pub fn test_ecfg_4() { execute_ecfg_discovery_test(vec![], vec![], vec![]) } +#[test] +pub fn test_ecfg_to_petri_net_4() { + execute_to_petri_net_test("test_ecfg_to_petri_net_4", vec![]); +} + #[test] pub fn test_ecfg_5() { execute_ecfg_discovery_test(vec![vecs![]], vecs!["START", "END"], vec!["[START]--[END]"]) } +#[test] +pub fn test_ecfg_to_petri_net_5() { + execute_to_petri_net_test("test_ecfg_to_petri_net_5", vec![vecs![]]); +} + #[test] pub fn test_ecfg_6() { execute_ecfg_discovery_test( @@ -109,6 +148,17 @@ pub fn test_ecfg_6() { ) } +#[test] +pub fn test_ecfg_to_petri_net_6() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_6", + vec![ + vecs!["A", "X", "B", "Y", "C", "Z", "D", "W", "E"], + vecs!["X", "A", "Y", "B", "Z", "C", "W", "D"], + ], + ); +} + #[test] pub fn test_ecfg_7() { execute_ecfg_discovery_test( @@ -138,6 +188,17 @@ pub fn test_ecfg_7() { ); } +#[test] +pub fn test_ecfg_to_petri_net_7() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_7", + vec![ + vecs!["X", "A", "Y", "B", "Z", "C", "W", "D", "Z", "E"], + vecs!["A", "B", "C", "D", "E"], + ], + ); +} + #[test] pub fn test_ecfg_8() { execute_ecfg_discovery_test( @@ -163,6 +224,19 @@ pub fn test_ecfg_8() { ); } +#[test] +pub fn test_ecfg_to_petri_net_8() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_8", + vec![ + vecs!["A", "B", "C", "D", "E"], + vecs!["A", "X", "B", "C", "D", "E"], + vecs!["A", "X", "C", "D", "E"], + vecs!["A", "X", "D", "E"], + ], + ); +} + #[test] pub fn test_ecfg_9() { execute_ecfg_discovery_test( @@ -193,6 +267,20 @@ pub fn test_ecfg_9() { ) } +#[test] +pub fn test_ecfg_to_petri_net_9() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_9", + vec![ + vecs!["A", "B", "C", "D", "E"], + vecs!["A", "X", "Y", "Z", "W", "B", "C", "D", "E"], + vecs!["A", "Y", "Z", "W", "B", "C", "D", "E"], + vecs!["A", "Z", "W", "B", "C", "D", "E"], + vecs!["A", "X", "B", "C", "D", "E"], + ], + ); +} + #[test] pub fn test_ecfg_10() { execute_ecfg_discovery_test( @@ -225,6 +313,19 @@ pub fn test_ecfg_10() { ) } +#[test] +pub fn test_ecfg_to_petri_net_10() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_10", + vec![ + vecs!["A", "B", "C", "D", "E"], + vecs!["A", "X", "Y", "Z", "W", "B", "C", "D", "E"], + vecs!["A", "y", "z", "w", "B", "C", "D", "E"], + vecs!["A", "V", "B", "C", "D", "E"], + ], + ); +} + #[test] pub fn test_ecfg_11() { execute_ecfg_discovery_test( @@ -344,7 +445,71 @@ pub fn test_ecfg_11() { ) } -fn execute_ecfg_discovery_test(mut traces: Vec>, gold_root_sequence: Vec, gold_graph_edges: Vec<&str>) { +#[test] +pub fn test_ecfg_to_petri_net_11() { + execute_to_petri_net_test( + "test_ecfg_to_petri_net_11", + vec![ + vecs!["5", "6", "7", "8", "0"], + vecs!["13", "1", "0", "9", "14"], + vecs![ + "13", "Loop[6]", "Loop[7]", "8", "Loop[15]", "18", "19", "20", "21", "17", "22", "Loop[23]", "Loop[24]", "8", "Loop[16]", "14" + ], + vecs!["13", "Loop[6]", "Loop[7]", "9", "Loop[26]", "23", "Loop[24]", "27", "8", "14"], + vecs![ + "5", "7", "0", "28", "26", "Loop[23]", "Loop[24]", "8", "16", "0", "28", "20", "21", "10" + ], + vecs!["5", "Loop[6]", "29", "7", "8", "Loop[17]", "11", "28", "8", "Loop[16]", "10"], + vecs![ + "5", "Loop[7]", "8", "0", "20", "21", "18", "19", "20", "21", "Loop[17]", "22", "Loop[26]", "8", "Loop[16]", "10" + ], + vecs![ + "13", "Loop[6]", "29", "Loop[7]", "8", "15", "30", "Loop[26]", "Loop[23]", "Loop[24]", "Loop[27]", "8", "Loop[0]", "28", "20", + "21", "16", "14" + ], + vecs![ + "5", "7", "31", "15", "18", "19", "20", "21", "Loop[17]", "11", "28", "Loop[26]", "23", "8", "Loop[16]", "10" + ], + ], + ); +} + +fn execute_ecfg_discovery_test(traces: Vec>, gold_root_sequence: Vec, gold_graph_edges: Vec<&str>) { + let graph = discover_ecfg_internal(traces, Some(gold_root_sequence)); + + let test_result = graph.serialize_edges_deterministic(false); + + let gold = gold_graph_edges.join("\n"); + + if test_result != gold { + let mut tgraph = DirectedGraph::new(); + tgraph.add_nodes(graph.all_nodes().into_iter().map(|n| (*n.id(), n.data().unwrap().to_owned()))); + tgraph.add_edges(graph.all_edges().into_iter().map(|e| (*e.from_node(), *e.to_node()))); + + let tconfig = Config::new(ValueFormatter::new(), 10).default_colors(); + + termgraph::display(&tgraph, &tconfig); + + println!("GOLD:"); + println!("{}", gold); + + println!("TEST RESULT:"); + println!("{}", test_result); + + assert!(false); + } +} + +fn execute_to_petri_net_test(test_name: &str, traces: Vec>) { + execute_test_with_gold(get_serialized_petri_nets_gold_path(test_name), || { + let graph = discover_ecfg_internal(traces, None); + let petri_net = convert_to_petri_net(&graph).ok().unwrap(); + + serialize_to_pnml(&petri_net, false).ok().unwrap() + }); +} + +fn discover_ecfg_internal(mut traces: Vec>, gold_root_sequence: Option>) -> DefaultGraph { const START: &'static str = "START"; const END: &'static str = "END"; @@ -355,7 +520,10 @@ fn execute_ecfg_discovery_test(mut traces: Vec>, gold_root_sequence: let root_sequence_kind = RootSequenceKind::FindBest; let root_sequence = discover_root_sequence(&traces, root_sequence_kind); - assert_eq!(root_sequence, gold_root_sequence); + + if let Some(gold_root_sequence) = gold_root_sequence { + assert_eq!(root_sequence, gold_root_sequence); + } let name_extractor = |s: &String| Arc::from(s.to_owned()); @@ -377,27 +545,5 @@ fn execute_ecfg_discovery_test(mut traces: Vec>, gold_root_sequence: .map(|t| t.into_iter().map(|e| EventWithUniqueId::new(e)).collect()) .collect(); - let graph = discover_ecfg(&traces, &context, false, None).ok().unwrap().graph_move(); - - let test_result = graph.serialize_edges_deterministic(false); - - let gold = gold_graph_edges.join("\n"); - - if test_result != gold { - let mut tgraph = DirectedGraph::new(); - tgraph.add_nodes(graph.all_nodes().into_iter().map(|n| (*n.id(), n.data().unwrap().to_owned()))); - tgraph.add_edges(graph.all_edges().into_iter().map(|e| (*e.from_node(), *e.to_node()))); - - let tconfig = Config::new(ValueFormatter::new(), 10).default_colors(); - - termgraph::display(&tgraph, &tconfig); - - println!("GOLD:"); - println!("{}", gold); - - println!("TEST RESULT:"); - println!("{}", test_result); - - assert!(false); - } + discover_ecfg(&traces, &context, false, None).ok().unwrap().graph_move() } diff --git a/Ficus/src/rust/ficus/tests/pipelines/pipeline_parts_tests.rs b/Ficus/src/rust/ficus/tests/pipelines/pipeline_parts_tests.rs index a1bf2bcc6..545fe9008 100644 --- a/Ficus/src/rust/ficus/tests/pipelines/pipeline_parts_tests.rs +++ b/Ficus/src/rust/ficus/tests/pipelines/pipeline_parts_tests.rs @@ -1,4 +1,4 @@ -use ficus::{pipelines::pipeline_parts::PipelineParts, vecs}; +use ficus::{pipelines::pipeline_parts::PIPELINE_PARTS, vecs}; fn get_test_parts_names() -> Vec { vecs![ @@ -97,18 +97,16 @@ fn get_test_parts_names() -> Vec { #[test] fn test_pipeline_parts() { - let parts = PipelineParts::new(); let names = get_test_parts_names(); for name in names { - assert!(parts.find_part(name.as_str()).is_some()); + assert!(PIPELINE_PARTS.find_part(name.as_str()).is_some()); } } #[test] fn test_pipeline_parts_count() { - let parts = PipelineParts::new(); let names = get_test_parts_names(); - assert_eq!(parts.len(), names.len()); + assert_eq!(PIPELINE_PARTS.len(), names.len()); } diff --git a/Ficus/src/rust/ficus_backend/src/grpc/backend_service.rs b/Ficus/src/rust/ficus_backend/src/grpc/backend_service.rs index befa2ab13..c8d2cb88c 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/backend_service.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/backend_service.rs @@ -9,7 +9,7 @@ use crate::{ }, grpc::{context_values_service::ContextValueService, pipeline_executor::ServicePipelineExecutionContext}, }; -use ficus::pipelines::pipeline_parts::PipelineParts; +use ficus::pipelines::pipeline_parts::PIPELINE_PARTS; use futures::Stream; use std::{pin::Pin, sync::Arc}; use tokio::sync::mpsc::{self, Sender}; @@ -21,15 +21,11 @@ pub(super) type GrpcSender = Sender, - pipeline_parts: Arc, } impl FicusService { pub fn new(cv_service: Arc) -> Self { - Self { - cv_service, - pipeline_parts: Arc::new(PipelineParts::new()), - } + Self { cv_service } } } @@ -41,7 +37,6 @@ impl GrpcBackendService for FicusService { &self, request: Request, ) -> Result, Status> { - let pipeline_parts = self.pipeline_parts.clone(); let (sender, receiver) = mpsc::channel(4); let context_values = match self.cv_service.reclaim_context_values(&request.get_ref().context_values_ids) { @@ -59,7 +54,7 @@ impl GrpcBackendService for FicusService { let sender = Arc::new(GrpcPipelineEventsHandler::new(sender)); let sender = sender as Arc; - let context = ServicePipelineExecutionContext::new(grpc_pipeline, &context_values, pipeline_parts, sender); + let context = ServicePipelineExecutionContext::new(grpc_pipeline, &context_values, sender); match context.execute_grpc_pipeline_and_fill_context_values(|_| Ok(()), cv_service) { Ok(uuid) => { @@ -85,8 +80,7 @@ impl GrpcBackendService for FicusService { async fn get_backend_info(&self, _: Request<()>) -> Result, Status> { Ok(Response::new(GrpcFicusBackendInfo { name: "RUST_FICUS_BACKEND".to_string(), - pipeline_parts: self - .pipeline_parts + pipeline_parts: PIPELINE_PARTS .pipeline_parts_descriptors() .into_iter() .map(|d| GrpcPipelinePartDescriptor { name: d.name() }) diff --git a/Ficus/src/rust/ficus_backend/src/grpc/context_values_service.rs b/Ficus/src/rust/ficus_backend/src/grpc/context_values_service.rs index e7ac77a25..067945bf7 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/context_values_service.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/context_values_service.rs @@ -180,6 +180,12 @@ impl GrpcContextValuesService for GrpcContextValueService { } } + async fn drop_context_values(&self, request: Request) -> Result, Status> { + self.cv_service.prune_context_values(&request.get_ref().ids); + + Ok(Response::new(())) + } + async fn get_context_value_id(&self, request: Request) -> Result, Status> { let key_name = &request.get_ref().key.as_ref().unwrap().name; match find_context_key(key_name) { @@ -202,10 +208,4 @@ impl GrpcContextValuesService for GrpcContextValueService { }) }) } - - async fn drop_context_values(&self, request: Request) -> Result, Status> { - self.cv_service.prune_context_values(&request.get_ref().ids); - - Ok(Response::new(())) - } } diff --git a/Ficus/src/rust/ficus_backend/src/grpc/get_context_pipeline.rs b/Ficus/src/rust/ficus_backend/src/grpc/get_context_pipeline.rs index f723defea..63def0aff 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/get_context_pipeline.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/get_context_pipeline.rs @@ -105,10 +105,7 @@ impl GetContextValuePipelinePart { } fn value_or_default(context: &PipelineContext, key: &DefaultContextKey, default_factory: impl Fn() -> T) -> T { - match context.concrete(key.key()) { - None => default_factory(), - Some(value) => value.clone(), - } + context.concrete(key.key()).cloned().unwrap_or_else(default_factory) } fn value_or_none(context: &PipelineContext, key: &DefaultContextKey) -> Option { diff --git a/Ficus/src/rust/ficus_backend/src/grpc/kafka/grpc_kafka_service.rs b/Ficus/src/rust/ficus_backend/src/grpc/kafka/grpc_kafka_service.rs index 138550ada..3e9577a13 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/kafka/grpc_kafka_service.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/kafka/grpc_kafka_service.rs @@ -18,9 +18,8 @@ use crate::{ }; use ficus::{ features::cases::CaseName, - pipelines::{ - keys::context_keys::{CASE_NAME_KEY, PIPELINE_ID_KEY, PIPELINE_NAME_KEY, PROCESS_NAME_KEY, SUBSCRIPTION_ID_KEY, SUBSCRIPTION_NAME_KEY}, - pipeline_parts::PipelineParts, + pipelines::keys::context_keys::{ + CASE_NAME_KEY, PIPELINE_ID_KEY, PIPELINE_NAME_KEY, PROCESS_NAME_KEY, SUBSCRIPTION_ID_KEY, SUBSCRIPTION_NAME_KEY, }, utils::user_data::user_data::UserData, }; @@ -34,16 +33,13 @@ use uuid::Uuid; pub struct GrpcKafkaServiceImpl { cv_service: Arc, kafka_service: Arc, - pipeline_parts: Arc, } impl GrpcKafkaServiceImpl { pub fn new(cv_service: Arc) -> Self { - let pipeline_parts = Arc::new(PipelineParts::default()); Self { cv_service: cv_service.clone(), - kafka_service: Arc::new(KafkaService::new(pipeline_parts.clone(), cv_service)), - pipeline_parts, + kafka_service: Arc::new(KafkaService::new(cv_service)), } } } @@ -213,7 +209,7 @@ impl GrpcKafkaService for GrpcKafkaServiceImpl { let handler = DelegatingEventsHandler::new(vec![kafka_handler, grpc_handler]); let handler = Arc::new(handler) as Arc; - let dto = PipelineExecutionDto::new(self.pipeline_parts.clone(), handler); + let dto = PipelineExecutionDto::new(handler); let context_values = match self .cv_service diff --git a/Ficus/src/rust/ficus_backend/src/grpc/kafka/kafka_service.rs b/Ficus/src/rust/ficus_backend/src/grpc/kafka/kafka_service.rs index f1beb9561..d96a46940 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/kafka/kafka_service.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/kafka/kafka_service.rs @@ -90,16 +90,14 @@ impl KafkaSubscription { } pub struct KafkaService { - pipeline_parts: Arc, subscriptions_to_execution_requests: Arc>>, cv_service: Arc, logger: ConsoleLogMessageHandler, } impl KafkaService { - pub fn new(pipeline_parts: Arc, cv_service: Arc) -> Self { + pub fn new(cv_service: Arc) -> Self { Self { - pipeline_parts, subscriptions_to_execution_requests: Arc::new(Mutex::new(HashMap::new())), logger: ConsoleLogMessageHandler::new(), cv_service, @@ -228,10 +226,7 @@ impl KafkaService { continue; }; - let execution_dto = PipelineExecutionDto::new( - Arc::new(PipelineParts::new()), - Arc::new(EmptyPipelineEventsHandler::new()) as Arc, - ); + let execution_dto = PipelineExecutionDto::new(Arc::new(EmptyPipelineEventsHandler::new()) as Arc); let trace_processing_context = KafkaTraceProcessingContext { execution_dto, trace }; @@ -284,7 +279,7 @@ impl KafkaService { }; let handler = handler as Arc; - let execution_dto = PipelineExecutionDto::new(Arc::new(PipelineParts::new()), handler); + let execution_dto = PipelineExecutionDto::new(handler); let context = Self::create_pipeline_execution_context(&pipeline.request, &execution_dto); let result = context.execute_grpc_pipeline_and_fill_context_values( @@ -341,7 +336,7 @@ impl KafkaService { streaming_config: StreamingConfiguration, ) -> KafkaSubscriptionPipeline { let handler = Arc::new(handler) as Arc; - let dto = PipelineExecutionDto::new(self.pipeline_parts.clone(), handler); + let dto = PipelineExecutionDto::new(handler); KafkaSubscriptionPipeline::new(request, dto, pipeline_name, streaming_config.create_processor()) } @@ -375,7 +370,7 @@ impl KafkaService { context_values: &'a Vec, dto: &PipelineExecutionDto, ) -> ServicePipelineExecutionContext<'a> { - ServicePipelineExecutionContext::new(pipeline, context_values, dto.pipeline_parts.clone(), dto.events_handler.clone()) + ServicePipelineExecutionContext::new(pipeline, context_values, dto.events_handler.clone()) } fn create_pipeline_execution_context<'a>( @@ -384,12 +379,7 @@ impl KafkaService { ) -> ServicePipelineExecutionContext<'a> { let grpc_pipeline = pipeline_req.pipeline.as_ref().expect("Pipeline should be supplied"); - ServicePipelineExecutionContext::new( - grpc_pipeline, - &pipeline_req.initial_context, - dto.pipeline_parts.clone(), - dto.events_handler.clone(), - ) + ServicePipelineExecutionContext::new(grpc_pipeline, &pipeline_req.initial_context, dto.events_handler.clone()) } pub(super) fn create_kafka_events_handler(producer_metadata: Option<&GrpcKafkaConnectionMetadata>) -> Result { diff --git a/Ficus/src/rust/ficus_backend/src/grpc/kafka/models.rs b/Ficus/src/rust/ficus_backend/src/grpc/kafka/models.rs index 865876d9a..6755fc5dd 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/kafka/models.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/kafka/models.rs @@ -9,7 +9,6 @@ use ficus::{ context::PipelineContext, errors::pipeline_errors::PipelinePartExecutionError, keys::context_keys::{CASE_NAME_KEY, PROCESS_NAME_KEY, UNSTRUCTURED_METADATA_KEY}, - pipeline_parts::PipelineParts, }, utils::user_data::user_data::UserData, }; @@ -69,16 +68,12 @@ impl Display for XesFromBxesKafkaTraceCreatingError { #[derive(Clone)] pub struct PipelineExecutionDto { - pub(super) pipeline_parts: Arc, pub(super) events_handler: Arc, } impl PipelineExecutionDto { - pub fn new(pipeline_parts: Arc, events_handler: Arc) -> Self { - Self { - pipeline_parts, - events_handler, - } + pub fn new(events_handler: Arc) -> Self { + Self { events_handler } } } diff --git a/Ficus/src/rust/ficus_backend/src/grpc/kafka/streaming/t2/processors.rs b/Ficus/src/rust/ficus_backend/src/grpc/kafka/streaming/t2/processors.rs index 78f405f60..735f1078a 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/kafka/streaming/t2/processors.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/kafka/streaming/t2/processors.rs @@ -55,7 +55,8 @@ impl T2StreamingProcessor { }; let xes_trace = if let Some(preprocessing_pipeline) = self.trace_preprocessing_pipeline.as_ref() { - let mut preprocessing_context = PipelineContext::default(); + let mut preprocessing_context = PipelineContext::empty(); + let mut log = XesEventLogImpl::default(); log.push(Rc::new(RefCell::new(xes_trace))); @@ -65,7 +66,6 @@ impl T2StreamingProcessor { let preprocessing_pipeline = ServicePipelineExecutionContext::new( preprocessing_pipeline, &initial_context_values, - context.execution_dto.pipeline_parts.clone(), context.execution_dto.events_handler.clone(), ); diff --git a/Ficus/src/rust/ficus_backend/src/grpc/logs_handler.rs b/Ficus/src/rust/ficus_backend/src/grpc/logs_handler.rs index 32517b4d1..bb0d8b4ad 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/logs_handler.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/logs_handler.rs @@ -22,7 +22,7 @@ impl GrpcLogMessageHandlerImpl { } #[derive(Clone)] -pub struct ConsoleLogMessageHandler {} +pub struct ConsoleLogMessageHandler; impl LogMessageHandler for ConsoleLogMessageHandler { fn handle(&self, message: &str) -> Result<(), PipelinePartExecutionError> { diff --git a/Ficus/src/rust/ficus_backend/src/grpc/pipeline_executor.rs b/Ficus/src/rust/ficus_backend/src/grpc/pipeline_executor.rs index 247eec2b7..ea2528025 100644 --- a/Ficus/src/rust/ficus_backend/src/grpc/pipeline_executor.rs +++ b/Ficus/src/rust/ficus_backend/src/grpc/pipeline_executor.rs @@ -13,7 +13,7 @@ use ficus::{ context::{LogMessageHandler, PipelineContext, PipelineInfrastructure}, errors::pipeline_errors::PipelinePartExecutionError, keys::context_keys::{EXECUTION_ID_KEY, find_context_key}, - pipeline_parts::PipelineParts, + pipeline_parts::PIPELINE_PARTS, pipelines::{DefaultPipelinePart, Pipeline, PipelinePart}, }, utils::{ @@ -27,7 +27,6 @@ use uuid::Uuid; pub(super) struct ServicePipelineExecutionContext<'a> { grpc_pipeline: &'a GrpcPipeline, context_values: &'a Vec, - pipeline_parts: Arc, handler: Arc, log_message_handler: Arc, } @@ -36,7 +35,6 @@ impl<'a> ServicePipelineExecutionContext<'a> { pub fn new( grpc_pipeline: &'a GrpcPipeline, context_values: &'a Vec, - pipeline_parts: Arc, handler: Arc, ) -> Self { let log_message_handler = Self::create_log_message_handler(handler.clone()); @@ -44,7 +42,6 @@ impl<'a> ServicePipelineExecutionContext<'a> { Self { grpc_pipeline, context_values, - pipeline_parts, handler, log_message_handler, } @@ -70,10 +67,6 @@ impl<'a> ServicePipelineExecutionContext<'a> { self.grpc_pipeline } - pub fn parts(&self) -> &PipelineParts { - &self.pipeline_parts - } - pub fn context_values(&self) -> &Vec { self.context_values } @@ -86,7 +79,6 @@ impl<'a> ServicePipelineExecutionContext<'a> { Self { grpc_pipeline: new_grpc_pipeline, context_values: self.context_values, - pipeline_parts: self.pipeline_parts.clone(), handler: self.handler.clone(), log_message_handler: self.log_message_handler.clone(), } @@ -211,14 +203,13 @@ impl<'a> ServicePipelineExecutionContext<'a> { } } - self - .parts() + PIPELINE_PARTS .find_part(&grpc_default_part.name) .map(|default_part| Box::new(default_part(Box::new(part_config)))) } - pub(super) fn create_initial_context(&'a self) -> PipelineContext<'a> { - let mut pipeline_context = PipelineContext::new_with_logging(self.parts()); + pub(super) fn create_initial_context(&'a self) -> PipelineContext { + let mut pipeline_context = PipelineContext::empty(); for value in self.context_values() { let key = find_context_key(&value.key.as_ref().unwrap().name).unwrap(); diff --git a/scripts/windows/generate_grpc_models.ps1 b/scripts/windows/generate_grpc_models.ps1 new file mode 100644 index 000000000..04f0c6d6e --- /dev/null +++ b/scripts/windows/generate_grpc_models.ps1 @@ -0,0 +1,18 @@ +$ErrorActionPreference = "Stop" + +Push-Location "$PSScriptRoot/../../Ficus/src/python/infra" +python generate_models.py ficus.grpc_pipelines ../ficus/grpc_pipelines/ ../../../protos +Pop-Location + +$env:GOPATH = "$HOME/go" +$env:PATH = "$env:PATH;$env:GOPATH/bin" + +Push-Location "$PSScriptRoot/../../Ficus/src/go/grpcmodels" +protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative --proto_path=../../../protos/ ../../../protos/*.proto +Pop-Location + +Push-Location "$PSScriptRoot/../../Ficus/src/front/FicusFrontend/FicusDashboard/Npm" +Get-ChildItem "../../../../../protos/*.proto" | ForEach-Object { + & .\node_modules\.bin\proto-loader-gen-types.ps1 --longs=Number --enums=number --defaults --oneofs --grpcLib=@grpc/grpc-js --outDir=./src/protos/ "../../../../../protos/$($_.Name)" --inputTemplate "%s_DONTUSE" --outputTemplate "%s" +} +Pop-Location \ No newline at end of file