runtime: filter stopped workers

This commit is contained in:
2026-07-29 04:27:04 +09:00
parent 98c1599d1a
commit acc7281414
6 changed files with 387 additions and 19 deletions
+18 -4
View File
@@ -234,6 +234,17 @@ struct RuntimeHttpConfigBundleAvailabilityQuery {
digest: String,
}
#[derive(Clone, Debug, Default, Deserialize)]
struct RuntimeHttpWorkersQuery {
status: Option<RuntimeHttpWorkerStatusFilter>,
}
#[derive(Clone, Copy, Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
enum RuntimeHttpWorkerStatusFilter {
Stopped,
}
/// `GET /v1/workers` response.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct RuntimeHttpWorkersResponse {
@@ -372,11 +383,14 @@ async fn check_config_bundle(
async fn list_workers(
State(state): State<RuntimeHttpState>,
query: Result<Query<RuntimeHttpWorkersQuery>, QueryRejection>,
) -> RestResult<RuntimeHttpWorkersResponse> {
let workers = state
.runtime
.list_workers()
.map_err(RuntimeHttpRestError::runtime)?;
let Query(query) = query.map_err(RuntimeHttpRestError::query_rejection)?;
let workers = match query.status {
Some(RuntimeHttpWorkerStatusFilter::Stopped) => state.runtime.list_stopped_workers(),
None => state.runtime.list_workers(),
}
.map_err(RuntimeHttpRestError::runtime)?;
Ok(Json(RuntimeHttpWorkersResponse { workers }))
}
+30 -3
View File
@@ -7,9 +7,7 @@ use crate::config_bundle::{
ConfigBundle, ConfigBundleAvailability, ConfigBundleSummary, validate_config_bundle,
validate_config_bundle_ref,
};
#[cfg(feature = "fs-store")]
use crate::diagnostics::DiagnosticSeverity;
use crate::diagnostics::RuntimeDiagnostic;
use crate::diagnostics::{DiagnosticSeverity, RuntimeDiagnostic};
use crate::error::RuntimeError;
use crate::execution::WorkerExecutionRestoreRequest;
use crate::execution::{
@@ -437,6 +435,17 @@ impl Runtime {
Ok(state.workers.values().map(WorkerRecord::summary).collect())
}
/// List stopped Workers known to this Runtime.
pub fn list_stopped_workers(&self) -> Result<Vec<WorkerSummary>, RuntimeError> {
let state = self.lock()?;
Ok(state
.workers
.values()
.filter(|worker| worker.status == WorkerStatus::Stopped)
.map(WorkerRecord::summary)
.collect())
}
/// Fetch Worker detail. The supplied [`WorkerRef`] must match this Runtime.
pub fn worker_detail(&self, worker_ref: &WorkerRef) -> Result<WorkerDetail, RuntimeError> {
let state = self.lock()?;
@@ -2049,6 +2058,24 @@ mod tests {
assert_eq!(fetched.profile, detail.profile);
}
#[test]
fn stopped_worker_list_excludes_alive_and_cancelled_workers() {
let runtime = runtime_with_backend();
let alive = runtime.create_worker(task_request("alive")).unwrap();
let stopped = runtime.create_worker(task_request("stopped")).unwrap();
let cancelled = runtime.create_worker(task_request("cancelled")).unwrap();
runtime.stop_worker(&stopped.worker_ref, None).unwrap();
runtime.cancel_worker(&cancelled.worker_ref, None).unwrap();
let candidates = runtime.list_stopped_workers().unwrap();
assert_eq!(candidates.len(), 1);
assert_eq!(candidates[0].worker_ref, stopped.worker_ref);
assert_eq!(candidates[0].status, WorkerStatus::Stopped);
assert_ne!(candidates[0].worker_ref, alive.worker_ref);
assert_ne!(candidates[0].worker_ref, cancelled.worker_ref);
}
#[test]
fn synced_config_bundle_is_stored_checked_and_used_for_worker_creation() {
let runtime = runtime_with_backend();