aion-server 0.31.0

Aion workflow server library: HTTP, gRPC, WebSocket, and worker endpoints. Run it with the `aion` binary from the aion-cli crate.
Documentation
//! How a reserved capacity slot becomes a tracked one.
//!
//! Split out of `heartbeat.rs` because it is a coherent decision with its own
//! reasoning — who owns the slot, and what happens to it in each case — and
//! because that file is over the size cap and may not grow.
//!
//! The whole surface is one function, and it exists because the transfer used
//! to be two acts under two registry locks. Between them a worker's `in_flight`
//! read one higher than the work it was holding, and a concurrent selection
//! landing in that window was refused a slot the worker demonstrably had:
//! measured at `in_flight = 5` on a worker advertising 4, on a fan sized exactly
//! to its pool, where the margin is zero and one collision is enough.

use crate::error::ServerError;
use crate::worker::ConnectedWorkerRegistry;
use crate::worker::registry::{DispatchReservation, WorkerId};

/// Settle the capacity slot for a dispatch that has just been tracked.
///
/// `first_tracking` is whether the tracker's insert actually added an entry, and
/// it is what decides ownership in both arms: the count must rise exactly once
/// per tracked dispatch, however many times that dispatch is tracked.
///
/// # Errors
///
/// Returns [`ServerError::LockPoisoned`] if the registry lock is poisoned while
/// raising the count for an unreserved dispatch.
pub(super) fn settle_reserved_slot(
    first_tracking: bool,
    worker_id: WorkerId,
    registry: &ConnectedWorkerRegistry,
    reservation: Option<DispatchReservation>,
) -> Result<(), ServerError> {
    // THE SLOT IS ALREADY HELD. The caller reserved it at selection and has
    // handed it over; committing transfers ownership WITHOUT the count ever
    // moving, so no concurrent selection can observe a worker holding more than
    // it really is.
    //
    // A duplicate track is the one case that releases instead: the existing
    // entry already owns a slot, so this reservation is a second claim on one
    // dispatch and must go back.
    if let Some(reservation) = reservation {
        if first_tracking {
            reservation.commit();
        } else {
            drop(reservation);
        }
        return Ok(());
    }
    // No reservation: this caller never claimed a slot — the in-process façades,
    // and any path tracking work it did not select. The count is raised here
    // instead, gated the same way.
    if first_tracking {
        registry.record_dispatch_started(worker_id)?;
    }
    Ok(())
}