use std::path::Path;
use aion_store::DesiredState;
use super::outcome::{AutoWorkerDecision, AutoWorkerOutcome};
pub(super) struct Subject<'a> {
pub(super) task_queue: &'a str,
pub(super) workflow_type: &'a str,
pub(super) name: &'a str,
pub(super) namespace: &'a str,
pub(super) document: &'a Path,
}
pub(super) fn written(
subject: &Subject<'_>,
decision: AutoWorkerDecision,
dial: &str,
) -> AutoWorkerOutcome {
if decision == AutoWorkerDecision::OperatorStopped {
return AutoWorkerOutcome::new(
subject.task_queue,
subject.workflow_type,
decision,
Some(subject.name.to_owned()),
format!(
"worker deployment `{name}` was rewritten onto this document (`{document}`) but \
LEFT STOPPED: an operator stopped it, and a redeploy is not a decision to undo \
that. Task queue `{queue}` is unserved until `aion worker start {name}`",
name = subject.name,
document = subject.document.display(),
queue = subject.task_queue
),
);
}
AutoWorkerOutcome::new(
subject.task_queue,
subject.workflow_type,
decision,
Some(subject.name.to_owned()),
format!(
"task queue `{queue}` declares a `harness` section, so worker deployment `{name}` was \
written to serve it with `aion worker agent {document} --liminal-address {dial} \
--namespace {namespace}`{tail}",
queue = subject.task_queue,
name = subject.name,
document = subject.document.display(),
namespace = subject.namespace,
tail = running_tail(decision, subject.namespace)
),
)
}
pub(super) fn unchanged(
subject: &Subject<'_>,
desired: DesiredState,
converged: bool,
) -> AutoWorkerOutcome {
let document = subject.document.display();
if desired == DesiredState::Stopped {
return AutoWorkerOutcome::new(
subject.task_queue,
subject.workflow_type,
AutoWorkerDecision::OperatorStopped,
Some(subject.name.to_owned()),
format!(
"worker deployment `{name}` already names this exact document (`{document}`) and \
is STOPPED because an operator stopped it. Nothing was rewritten and it was not \
started; task queue `{queue}` is unserved until `aion worker start {name}`",
name = subject.name,
queue = subject.task_queue
),
);
}
let decision = if converged {
AutoWorkerDecision::Unchanged
} else {
AutoWorkerDecision::RecordedNotRunning
};
AutoWorkerOutcome::new(
subject.task_queue,
subject.workflow_type,
decision,
Some(subject.name.to_owned()),
format!(
"worker deployment `{name}` already serves task queue `{queue}` from this exact \
document (`{document}`), so nothing was rewritten and its worker was not \
restarted{tail}",
name = subject.name,
queue = subject.task_queue,
tail = if converged {
""
} else {
" — and it is NOT running on this server; see the supervision failure logged \
beside this line"
}
),
)
}
pub(super) fn dark_outbox(
task_queue: &str,
workflow_type: &str,
dark: &super::listener::DarkOutbox,
) -> AutoWorkerOutcome {
AutoWorkerOutcome::new(
task_queue,
workflow_type,
AutoWorkerDecision::DarkOutbox,
None,
format!(
"task queue `{task_queue}` declares a `harness` section, so this server would stand a \
built-in agent worker up for it — but {dark}. NOTHING was minted: a deployment \
record replays its argv verbatim, and one naming an address no listener answers on \
would fail on every restart until its crash-loop budget parked it"
),
)
}
pub(super) fn unrunnable_harness(
task_queue: &str,
workflow_type: &str,
why: &str,
) -> AutoWorkerOutcome {
AutoWorkerOutcome::new(
task_queue,
workflow_type,
AutoWorkerDecision::UnrunnableHarness,
None,
format!(
"task queue `{task_queue}` declares a `harness` section, so this server would stand a built-in agent worker up for it — but {why}. NOTHING was minted: a worker whose agent cannot spawn on this host fails every dispatch routed to it, burning an attempt each time while the worker that CAN serve the queue never sees the task. Deploy this document to the host its harness names, or fix the paths it declares"
),
)
}
pub(super) fn failure(task_queue: &str, workflow_type: &str, detail: String) -> AutoWorkerOutcome {
AutoWorkerOutcome::new(
task_queue,
workflow_type,
AutoWorkerDecision::Failed,
None,
detail,
)
}
fn running_tail(decision: AutoWorkerDecision, namespace: &str) -> String {
if decision.claims_running() {
format!(
", and this server started it. It serves namespace `{namespace}` ONLY: a run started \
in another namespace is not dispatched to it"
)
} else {
String::from(
" — and this server could NOT start it. The record is durable and the next boot's \
reconcile honours it; see the supervision failure logged beside this line",
)
}
}