Public dry run dryrun-199c53541aa2
This commit is contained in:
parent
c8526c39ef
commit
84ef57d84b
5 changed files with 304 additions and 12 deletions
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue