use aion_core::{Event, Payload, RunId, WorkflowId};
use aion_package::ContentHash;
use crate::error::EngineError;
use crate::loader::{WorkflowCatalog, parse_package_version};
use crate::registry::WorkflowHandle;
pub(crate) fn admit_against_handle(
catalog: &WorkflowCatalog,
handle: &WorkflowHandle,
signal_name: &str,
payload: &Payload,
) -> Result<(), EngineError> {
admit(
catalog,
handle.workflow_id(),
handle.run_id(),
handle.workflow_type(),
handle.loaded_version(),
signal_name,
payload,
)
}
pub(crate) fn admit_against_history(
catalog: &WorkflowCatalog,
workflow_id: &WorkflowId,
run_id: &RunId,
history: &[Event],
signal_name: &str,
payload: &Payload,
) -> Result<(), EngineError> {
let Some((workflow_type, package_version)) = started_identity(history, run_id) else {
return Ok(());
};
let version = match parse_package_version(workflow_type, package_version) {
Ok(version) => version,
Err(error) => {
tracing::warn!(
%workflow_id,
%run_id,
workflow_type,
%package_version,
signal_name,
%error,
"run's recorded package version is not a canonical content hash; no declaration could be resolved to admit this signal against"
);
return Ok(());
}
};
admit(
catalog,
workflow_id,
run_id,
workflow_type,
&version,
signal_name,
payload,
)
}
fn started_identity<'a>(
history: &'a [Event],
run_id: &RunId,
) -> Option<(&'a str, &'a aion_core::PackageVersion)> {
history.iter().find_map(|event| match event {
Event::WorkflowStarted {
workflow_type,
run_id: started_run,
package_version,
..
} if started_run == run_id => Some((workflow_type.as_str(), package_version)),
_ => None,
})
}
fn admit(
catalog: &WorkflowCatalog,
workflow_id: &WorkflowId,
run_id: &RunId,
workflow_type: &str,
version: &ContentHash,
signal_name: &str,
payload: &Payload,
) -> Result<(), EngineError> {
let Some(reason) =
catalog.declared_signal_refusal(workflow_type, version, signal_name, payload)?
else {
return Ok(());
};
Err(EngineError::SignalRefused {
workflow_id: workflow_id.clone(),
run_id: run_id.clone(),
signal_name: signal_name.to_owned(),
version: version.clone(),
reason: reason.to_string(),
})
}