aion-server 0.27.1

Aion workflow server library: HTTP, gRPC, WebSocket, and worker endpoints. Run it with the `aion` binary from the aion-cli crate.
Documentation
//! One triage for every "the record is written; now make it so" call site.
//!
//! Three callers converge a record they have just made durable — the
//! worker-deployment PUT, the desired-state POST, and auto-provision — and all
//! three owe the operator the same reading of a failure. Two of the outcomes
//! are not faults and must not be logged as though they were:
//!
//! - [`SupervisionError::NotCommissioned`] — this server has no
//!   `[worker_supervision]` policy. The durable record stands and the next
//!   boot's reconcile honours it once a policy exists; the remedy travels with
//!   the error.
//! - [`SupervisionError::UnknownDeployment`] — the record was removed between
//!   the write and the convergence. That is a race with another operator.
//!
//! Everything else — a process group that could not be proven empty, a
//! poisoned state cell, a store that refused — is an operator-actionable fault
//! and is logged at `error`. Collapsing all of them to one severity is how a
//! leaked process group becomes a line somebody scrolls past.

use std::sync::Arc;

use super::error::SupervisionError;
use super::fleet::{Convergence, WorkerSupervisor};
use super::status::ManagedWorkerStatus;

/// Converge one already-written record, log the outcome at the severity it
/// earns, and hand the result back so the caller can say what actually happened.
///
/// The result is RETURNED rather than swallowed on purpose: a caller that
/// reports "and this server started it" without reading it would be making
/// exactly the claim this whole lane exists to stop anyone making.
///
/// # Errors
///
/// Returns whatever [`WorkerSupervisor::converge`] returned, unchanged.
pub async fn converge_and_report(
    supervisor: &Arc<WorkerSupervisor>,
    name: &str,
    mode: Convergence,
    operation: &'static str,
) -> Result<ManagedWorkerStatus, SupervisionError> {
    let converged = supervisor.converge(name, mode).await;
    match &converged {
        Ok(status) => tracing::info!(
            operation,
            worker = name,
            desired = status.desired.token(),
            state = status.state.token(),
            "worker deployment converged on the node that accepted it"
        ),
        Err(error @ SupervisionError::NotCommissioned) => tracing::warn!(
            operation,
            worker = name,
            remedy = error.remedy(),
            "the worker deployment was written durably but nothing supervises it on this server"
        ),
        Err(error @ SupervisionError::UnknownDeployment { .. }) => tracing::warn!(
            operation,
            worker = name,
            %error,
            "the worker deployment was removed before this node could converge it"
        ),
        Err(error) => tracing::error!(
            operation,
            worker = name,
            %error,
            "the worker deployment was written durably but could not be converged on this node"
        ),
    }
    converged
}