use super::*;
pub fn execute<C: Credentials, P: Probe>(
context: &Context<'_, C, P>,
selected: &Instance,
deadline: Instant,
) -> Result<Started> {
let _operation = operation_lock(context.store, deadline)?;
let registered = context.store.read()?;
let current = crate::storage::state::select(®istered, Some(&selected.id))?;
crate::napcat::runtime::version_intent::guard_start(
context.store,
context.references,
®istered,
¤t,
)?;
crate::napcat::runtime::startup::inspect(
context.store,
®istered,
context.release,
context.witnesses,
context.probe,
deadline,
)?;
if current.run_id != selected.run_id {
let mut source = selected.clone();
source.state = "stopped".into();
return existing::locked(context, &source, deadline);
}
if matches!(current.state.as_str(), "starting" | "unknown") {
return Err(unknown_instance(¤t.id, None));
}
if matches!(selected.state.as_str(), "preparing" | "prepared")
&& crate::napcat::runtime::instance_creation::transition::matches(¤t, selected)
&& crate::napcat::runtime::generation::active(
context.store,
context.references,
¤t,
deadline,
)?
.is_some()
{
if !matches!(
current.state.as_str(),
"preparing" | "prepared" | "ready" | "login_required"
) {
return Err(AppError::new(
"START_INPUTS_CHANGED",
"The selected successor preparation is no longer active; no stopped run was restarted.",
4,
));
}
return existing::locked(context, ¤t, deadline);
}
crate::napcat::runtime::stop::locked(context.store, context.references, selected, deadline)?;
let stopped = crate::storage::state::select(&context.store.read()?, Some(&selected.id))?;
let mut expected = selected.clone();
expected.state = "stopped".into();
if stopped != expected {
return Err(unknown_instance(&selected.id, None));
}
existing::locked(context, &stopped, deadline)
}