making linters happy
Some checks failed
CI / Rust Blocking Checks (push) Failing after 22s
CI / Web Blocking Checks (push) Failing after 26s
CI / Security Blocking Checks (push) Successful in 9s
CI / Web Advisory Checks (push) Successful in 32s
CI / Security Advisory Checks (push) Has been cancelled

This commit is contained in:
2026-03-04 23:44:45 -06:00
parent 6a5a3c2b78
commit 13749409cd
81 changed files with 468 additions and 599 deletions

View File

@@ -116,13 +116,7 @@ impl CompletionListener {
// Verify execution exists in database
let execution = ExecutionRepository::find_by_id(pool, execution_id).await?;
if execution.is_none() {
warn!(
"Execution {} not found in database, but still releasing queue slot",
execution_id
);
} else {
let exec = execution.as_ref().unwrap();
if let Some(ref exec) = execution {
debug!(
"Execution {} found with status: {:?}",
execution_id, exec.status
@@ -180,6 +174,11 @@ impl CompletionListener {
}
}
}
} else {
warn!(
"Execution {} not found in database, but still releasing queue slot",
execution_id
);
}
// Release queue slot for this action

View File

@@ -77,8 +77,7 @@ impl DeadLetterHandler {
info!("Dead letter handler stopping, rejecting message");
return Err(attune_common::mq::MqError::Consume(
"Handler is shutting down".to_string(),
)
.into());
));
}
}

View File

@@ -189,7 +189,7 @@ impl EventProcessor {
let payload_dict = payload
.as_object()
.cloned()
.unwrap_or_else(|| serde_json::Map::new());
.unwrap_or_else(serde_json::Map::new);
// Resolve action parameters using the template resolver
let resolved_params = Self::resolve_action_params(pool, rule, event, &payload).await?;
@@ -248,7 +248,7 @@ impl EventProcessor {
};
// If rule has no conditions, it always matches
if rule.conditions.is_null() || rule.conditions.as_array().map_or(true, |a| a.is_empty()) {
if rule.conditions.is_null() || rule.conditions.as_array().is_none_or(|a| a.is_empty()) {
debug!("Rule {} has no conditions, matching by default", rule.r#ref);
return Ok(true);
}
@@ -364,7 +364,7 @@ impl EventProcessor {
let action_params = &rule.action_params;
// If there are no action params, return empty
if action_params.is_null() || action_params.as_object().map_or(true, |o| o.is_empty()) {
if action_params.is_null() || action_params.as_object().is_none_or(|o| o.is_empty()) {
return Ok(serde_json::Map::new());
}

View File

@@ -257,7 +257,6 @@ mod tests {
fn test_execution_manager_creation() {
// This is a placeholder test
// Real tests will require database and message queue setup
assert!(true);
}
#[test]

View File

@@ -21,6 +21,7 @@ use crate::queue_manager::ExecutionQueueManager;
/// Policy violation type
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[allow(clippy::enum_variant_names)]
pub enum PolicyViolation {
/// Rate limit exceeded
RateLimitExceeded {
@@ -78,7 +79,7 @@ impl std::fmt::Display for PolicyViolation {
}
/// Execution policy configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ExecutionPolicy {
/// Rate limit: maximum executions per time window
pub rate_limit: Option<RateLimit>,
@@ -88,16 +89,6 @@ pub struct ExecutionPolicy {
pub quotas: Option<HashMap<String, u64>>,
}
impl Default for ExecutionPolicy {
fn default() -> Self {
Self {
rate_limit: None,
concurrency_limit: None,
quotas: None,
}
}
}
/// Rate limit configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RateLimit {

View File

@@ -78,11 +78,7 @@ fn apply_param_defaults(params: JsonValue, param_schema: &Option<JsonValue>) ->
if let Some(schema_obj) = schema.as_object() {
for (key, prop) in schema_obj {
// Only fill in missing / null parameters
let needs_default = match obj.get(key) {
None => true,
Some(JsonValue::Null) => true,
_ => false,
};
let needs_default = matches!(obj.get(key), None | Some(JsonValue::Null));
if needs_default {
if let Some(default_val) = prop.get("default") {
debug!("Applying default for parameter '{}': {}", key, default_val);
@@ -411,6 +407,7 @@ impl ExecutionScheduler {
/// `triggered_by` is the name of the predecessor task whose completion
/// caused this task to be scheduled. Pass `None` for entry-point tasks
/// dispatched at workflow start.
#[allow(clippy::too_many_arguments)]
async fn dispatch_workflow_task(
pool: &PgPool,
publisher: &Publisher,
@@ -496,10 +493,8 @@ impl ExecutionScheduler {
let task_config: Option<JsonValue> =
if rendered_input.is_object() && !rendered_input.as_object().unwrap().is_empty() {
Some(rendered_input.clone())
} else if let Some(parent_config) = &parent_execution.config {
Some(parent_config.clone())
} else {
None
parent_execution.config.clone()
};
// Build workflow task metadata
@@ -660,10 +655,8 @@ impl ExecutionScheduler {
let task_config: Option<JsonValue> =
if rendered_input.is_object() && !rendered_input.as_object().unwrap().is_empty() {
Some(rendered_input.clone())
} else if let Some(parent_config) = &parent_execution.config {
Some(parent_config.clone())
} else {
None
parent_execution.config.clone()
};
let workflow_task = WorkflowTaskMetadata {
@@ -1108,16 +1101,16 @@ impl ExecutionScheduler {
let mut task_results_map: HashMap<String, JsonValue> = HashMap::new();
for child in &child_executions {
if let Some(ref wt) = child.workflow_task {
if wt.workflow_execution == workflow_execution_id {
if matches!(
if wt.workflow_execution == workflow_execution_id
&& matches!(
child.status,
ExecutionStatus::Completed
| ExecutionStatus::Failed
| ExecutionStatus::Timeout
) {
let result_val = child.result.clone().unwrap_or(serde_json::json!({}));
task_results_map.insert(wt.task_name.clone(), result_val);
}
)
{
let result_val = child.result.clone().unwrap_or(serde_json::json!({}));
task_results_map.insert(wt.task_name.clone(), result_val);
}
}
}
@@ -1514,7 +1507,7 @@ impl ExecutionScheduler {
// Filter by heartbeat freshness (only workers with recent heartbeats)
let fresh_workers: Vec<_> = active_workers
.into_iter()
.filter(|w| Self::is_worker_heartbeat_fresh(w))
.filter(Self::is_worker_heartbeat_fresh)
.collect();
if fresh_workers.is_empty() {
@@ -1749,27 +1742,23 @@ mod tests {
fn test_scheduler_creation() {
// This is a placeholder test
// Real tests will require database and message queue setup
assert!(true);
}
#[test]
fn test_concurrency_limit_dispatch_count() {
// Verify the dispatch_count calculation used by dispatch_with_items_task
let total = 20usize;
let concurrency: Option<usize> = Some(3);
let concurrency_limit = concurrency.unwrap_or(total);
let concurrency_limit = 3usize;
let dispatch_count = total.min(concurrency_limit);
assert_eq!(dispatch_count, 3);
// No concurrency limit → default to serial (1 at a time)
let concurrency: Option<usize> = None;
let concurrency_limit = concurrency.unwrap_or(1);
let concurrency_limit = 1usize;
let dispatch_count = total.min(concurrency_limit);
assert_eq!(dispatch_count, 1);
// Concurrency exceeds total → dispatch all
let concurrency: Option<usize> = Some(50);
let concurrency_limit = concurrency.unwrap_or(total);
let concurrency_limit = 50usize;
let dispatch_count = total.min(concurrency_limit);
assert_eq!(dispatch_count, 20);
}

View File

@@ -406,7 +406,7 @@ impl WorkerHealthProbe {
runtime_array.iter().any(|v| {
v.as_str()
.map_or(false, |s| s.eq_ignore_ascii_case(runtime_name))
.is_some_and(|s| s.eq_ignore_ascii_case(runtime_name))
})
}
}

View File

@@ -1129,7 +1129,7 @@ mod tests {
let mut publish_map = HashMap::new();
publish_map.insert("flag".to_string(), JsonValue::Bool(true));
publish_map.insert("count".to_string(), json!(42));
publish_map.insert("ratio".to_string(), json!(3.14));
publish_map.insert("ratio".to_string(), json!(3.15));
publish_map.insert("nothing".to_string(), JsonValue::Null);
publish_map.insert(
"template".to_string(),
@@ -1152,7 +1152,7 @@ mod tests {
assert!(ctx.get_var("count").unwrap().is_number());
// Float preserved
assert_eq!(ctx.get_var("ratio").unwrap(), json!(3.14));
assert_eq!(ctx.get_var("ratio").unwrap(), json!(3.15));
// Null preserved
assert_eq!(ctx.get_var("nothing").unwrap(), json!(null));

View File

@@ -965,7 +965,7 @@ tasks:
publish:
- validation_passed: true
- count: 42
- ratio: 3.14
- ratio: 3.15
- label: "hello"
- template_val: "{{ result().data }}"
- nothing: null
@@ -1003,7 +1003,7 @@ tasks:
assert_eq!(publish_map["count"], &serde_json::json!(42));
// Float is preserved as a JSON number
assert_eq!(publish_map["ratio"], &serde_json::json!(3.14));
assert_eq!(publish_map["ratio"], &serde_json::json!(3.15));
// Plain string stays as a string
assert_eq!(