Public dry run dryrun-199c53541aa2

This commit is contained in:
Michel Paulissen 2026-07-03 20:31:07 +02:00
parent c8526c39ef
commit 84ef57d84b
5 changed files with 304 additions and 12 deletions

View file

@ -442,6 +442,16 @@ impl Coordinator {
self.active_processes.get(id)
}
pub fn active_process_for_project(
&self,
tenant: &TenantId,
project: &ProjectId,
) -> Option<&ActiveProcess> {
self.active_processes
.values()
.find(|active| &active.tenant == tenant && &active.project == project)
}
pub fn active_process_count(&self) -> usize {
self.active_processes.len()
}

View file

@ -151,6 +151,8 @@ pub enum CoordinatorRequest {
tenant: String,
project: String,
process: String,
#[serde(default)]
restart: bool,
},
ReconnectNode {
node: String,
@ -1160,10 +1162,23 @@ impl CoordinatorService {
tenant,
project,
process,
restart,
} => {
let tenant = TenantId::new(tenant);
let project = ProjectId::new(project);
let process = ProcessId::new(process);
if let Some(active) = self
.coordinator
.active_process_for_project(&tenant, &project)
{
if active.id != process || !restart {
return Err(CoordinatorError::Unauthorized(format!(
"project already has active virtual process {}; inspect it, restart it, cancel it, or wait before starting another run",
active.id
))
.into());
}
}
self.process_cancellations
.remove(&process_control_key(&tenant, &project, &process));
self.task_cancellations.retain(
@ -2299,6 +2314,7 @@ mod tests {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process".to_owned(),
restart: false,
})
.unwrap();
assert_eq!(
@ -2460,6 +2476,7 @@ mod tests {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process".to_owned(),
restart: false,
})
.unwrap();
service
@ -2596,6 +2613,7 @@ mod tests {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process".to_owned(),
restart: false,
})
.unwrap();
for node in ["node-a", "node-b"] {
@ -2703,6 +2721,63 @@ mod tests {
.contains("virtual process is cancelling"));
}
#[test]
fn service_rejects_second_active_process_unless_restarting_same_process() {
let mut service = CoordinatorService::new(7);
let started = service
.handle_request(CoordinatorRequest::StartProcess {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process-a".to_owned(),
restart: false,
})
.unwrap();
assert!(matches!(
started,
CoordinatorResponse::ProcessStarted { .. }
));
let same_without_restart = service
.handle_request(CoordinatorRequest::StartProcess {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process-a".to_owned(),
restart: false,
})
.unwrap_err();
assert!(same_without_restart
.to_string()
.contains("already has active virtual process"));
let other_process = service
.handle_request(CoordinatorRequest::StartProcess {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process-b".to_owned(),
restart: true,
})
.unwrap_err();
assert!(other_process
.to_string()
.contains("already has active virtual process"));
let restarted = service
.handle_request(CoordinatorRequest::StartProcess {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process-a".to_owned(),
restart: true,
})
.unwrap();
assert_eq!(
restarted,
CoordinatorResponse::ProcessStarted {
process: ProcessId::from("process-a"),
epoch: 7,
}
);
}
#[test]
fn service_download_links_are_scoped_and_streaming_is_metered() {
let mut service = CoordinatorService::new(7);
@ -2719,6 +2794,7 @@ mod tests {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process".to_owned(),
restart: false,
})
.unwrap();
service
@ -3067,6 +3143,7 @@ mod tests {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process".to_owned(),
restart: false,
})
.unwrap();
service
@ -3241,6 +3318,7 @@ mod tests {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "process".to_owned(),
restart: false,
})
.unwrap();
@ -3492,6 +3570,7 @@ mod tests {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "vp-control".to_owned(),
restart: false,
})
.unwrap()
else {
@ -3569,6 +3648,7 @@ mod tests {
tenant: "tenant".to_owned(),
project: "project".to_owned(),
process: "vp-control".to_owned(),
restart: false,
})
.unwrap();
@ -3702,6 +3782,7 @@ mod tests {
tenant: "tenant-b".to_owned(),
project: "project-b".to_owned(),
process: "process".to_owned(),
restart: false,
})
.unwrap();