huskies: merge 994
This commit is contained in:
@@ -6,7 +6,23 @@ use std::collections::HashMap;
|
||||
use super::super::super::{AgentStatus, PipelineStage, agent_config_stage, pipeline_stage};
|
||||
use super::super::StoryAgent;
|
||||
|
||||
/// Return `true` if the agent has a throttle set whose expiry has already passed.
|
||||
///
|
||||
/// Returns `false` when the agent has no throttle, or when the throttle's
|
||||
/// `until` time is still in the future (throttle is active, agent is waiting).
|
||||
fn is_throttle_expired(agent: &StoryAgent) -> bool {
|
||||
agent
|
||||
.throttled
|
||||
.as_ref()
|
||||
.map(|e| !e.is_active())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Return `true` if `agent_name` has no active (pending/running) entry in the pool.
|
||||
///
|
||||
/// An agent with an expired throttle is considered free even if its status
|
||||
/// is still `Running` — the scheduler may retry rather than skip indefinitely.
|
||||
/// Agents without any throttle (or with an active throttle) are still considered busy.
|
||||
pub(in crate::agents::pool) fn is_agent_free(
|
||||
agents: &HashMap<String, StoryAgent>,
|
||||
agent_name: &str,
|
||||
@@ -14,6 +30,7 @@ pub(in crate::agents::pool) fn is_agent_free(
|
||||
!agents.values().any(|a| {
|
||||
a.agent_name == agent_name
|
||||
&& matches!(a.status, AgentStatus::Running | AgentStatus::Pending)
|
||||
&& !is_throttle_expired(a)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -148,7 +165,7 @@ mod tests {
|
||||
project_root: None,
|
||||
log_session_id: None,
|
||||
merge_failure_reported: false,
|
||||
throttled: false,
|
||||
throttled: None,
|
||||
termination_reason: None,
|
||||
status_buffer: None,
|
||||
}
|
||||
@@ -569,6 +586,51 @@ model = "sonnet"
|
||||
assert_eq!(free, Some("qa"));
|
||||
}
|
||||
|
||||
// ── is_agent_free: throttle-expiry behaviour ─────────────────────────
|
||||
|
||||
#[test]
|
||||
fn is_agent_free_returns_false_for_running_agent_no_throttle() {
|
||||
let mut agents = HashMap::new();
|
||||
agents.insert(
|
||||
"s1:coder-1".to_string(),
|
||||
make_test_story_agent("coder-1", AgentStatus::Running),
|
||||
);
|
||||
assert!(
|
||||
!is_agent_free(&agents, "coder-1"),
|
||||
"running agent with no throttle should be busy"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_agent_free_returns_false_for_running_agent_with_active_throttle() {
|
||||
let mut agent = make_test_story_agent("coder-1", AgentStatus::Running);
|
||||
// Throttle expires far in the future → still active.
|
||||
agent.throttled = Some(crate::agents::AgentExecution::Throttled {
|
||||
until: chrono::Utc::now() + chrono::Duration::hours(1),
|
||||
});
|
||||
let mut agents = HashMap::new();
|
||||
agents.insert("s1:coder-1".to_string(), agent);
|
||||
assert!(
|
||||
!is_agent_free(&agents, "coder-1"),
|
||||
"running agent with active throttle should still be busy"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_agent_free_returns_true_for_running_agent_with_expired_throttle() {
|
||||
let mut agent = make_test_story_agent("coder-1", AgentStatus::Running);
|
||||
// Throttle expired in the past → agent is eligible for retry.
|
||||
agent.throttled = Some(crate::agents::AgentExecution::Throttled {
|
||||
until: chrono::Utc::now() - chrono::Duration::minutes(1),
|
||||
});
|
||||
let mut agents = HashMap::new();
|
||||
agents.insert("s1:coder-1".to_string(), agent);
|
||||
assert!(
|
||||
is_agent_free(&agents, "coder-1"),
|
||||
"running agent with expired throttle should be considered free"
|
||||
);
|
||||
}
|
||||
|
||||
// ── count_active_agents_for_stage ────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user