veredictum 0.1.4

The independent conformance instrument for openEHR clinical data repositories: a machine-readable catalogue of spec-cited test cases, executed against any running CDR, judged by pure-function verdicts
Documentation
// SPDX-FileCopyrightText: Veredictum contributors
// SPDX-License-Identifier: Apache-2.0

//! The performance measurement machinery.
//!
//! This is the OPEN-LOOP driver that
//! executes a `kind: performance` case's hospital-simulation workload
//! against a live SUT and produces the re-checkable
//! [`crate::perf::Measurement`] record.
//!
//! The offered load is a deterministic seeded arrival schedule of clinical
//! JOURNEYS (`vocab/journey_catalogue.yaml`): every stage of every journey
//! instance is a planned arrival instant on the global schedule (an order
//! at `t`, its administrations at `t + k·interval`, the laboratory result
//! at `t + Δ`), and the dispatcher fires each at its instant regardless of
//! any other operation's completion — journeys interleave exactly as wards
//! do, never closed-loop users. Every latency is measured from the PLANNED
//! arrival instant, so coordinated omission cannot hide stalls (the
//! `hdrhistogram` crate documents the same correction model). A dependent
//! stage whose prerequisite has not landed at fire time (a stalled SUT)
//! records honestly as an error arrival.
//!
//! Module map: [`client`] the blocking SUT client · [`pack`] the CKM
//! template pack + payload stamping · [`jitter`] the template-constrained
//! numeric-leaf redraw the stamping applies · [`corpus`] the seeded scale
//! corpus + the standing ward · [`schedule`] journey expansion into planned
//! arrivals (uniform + diurnal curves) · [`execute`] the per-stage wire
//! realization + captured-id state · [`window`] the measured window core
//! shared by the class runs (conformance) and the stress ladder
//! (exploration) · [`resources`] the per-container resource sampler + disk
//! anchors (measured context, never verdict-bearing).

pub mod client;
pub mod corpus;
pub mod execute;
pub mod jitter;
pub mod pack;
pub mod resources;
pub mod schedule;
pub mod window;

/// FNV-1a over a stream seed plus the caller's index parts: the deterministic
/// draw shared by the arrival schedule and the payload jitter, each carrying
/// its own seed so the two streams never correlate.
///
/// The parameters and the 64-bit offset basis are the reference ones
/// (<http://www.isthe.com/chongo/tech/comp/fnv/index.html>).
pub(crate) fn fnv1a(seed: u64, parts: &[u64]) -> u64 {
    let mut hash: u64 = 0xcbf2_9ce4_8422_2325 ^ seed;
    for part in parts {
        for byte in part.to_le_bytes() {
            hash ^= u64::from(byte);
            hash = hash.wrapping_mul(0x0000_0100_0000_01b3);
        }
    }
    hash
}

/// Set the moment any arrival observes `429 Too Many Requests`.
///
/// A measured record must describe the SERVER's ceiling. If the SUT rate-limits
/// the instrument, the ceiling being measured is the limiter's instead — the
/// ladder reaches 1024 requests/second from one principal and one address, so
/// an enabled limiter WILL bite, and the resulting numbers would be a
/// configuration artefact wearing a measurement's clothes. Both instruments
/// consult this before writing a record and refuse rather than publish one.
static RATE_LIMITED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);

/// Records that the SUT rate-limited an arrival.
pub(crate) fn note_rate_limited() {
    RATE_LIMITED.store(true, std::sync::atomic::Ordering::Relaxed);
}

/// Whether any arrival in this process was rate-limited.
#[must_use]
pub fn rate_limited_observed() -> bool {
    RATE_LIMITED.load(std::sync::atomic::Ordering::Relaxed)
}

/// The refusal message both instruments emit, naming the fix.
#[must_use]
pub fn rate_limited_refusal(instrument: &str) -> String {
    format!(
        "{instrument}: the SUT answered 429 — the measurement would record the \
         rate limiter's ceiling, not the server's. Measurement requires the \
         SUT's rate limiter disabled, or raised above the ladder's peak \
         arrival rate, for the duration of the window; the switch that does \
         that is the SUT's own, and the party declares it in its IXIT. Run \
         again once the window is unlimited."
    )
}

/// Decides whether a finished window may become a published record.
///
/// Both measured instruments consult this at the seam where a window would
/// reach a results document, so one 429 anywhere in the process withholds
/// the record for `instrument` in exactly one place.
///
/// # Errors
/// [`rate_limited_refusal`] for `instrument` once any arrival in this process
/// observed `429 Too Many Requests`.
pub fn refuse_rate_limited_record(instrument: &str) -> Result<(), String> {
    if rate_limited_observed() {
        return Err(rate_limited_refusal(instrument));
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::{note_rate_limited, rate_limited_observed, refuse_rate_limited_record};

    // NOTE: nextest runs each test in its own process
    // (<https://nexte.st/docs/design/how-it-works/>), so the two directions of
    // this process-global latch never observe each other.

    /// A window no arrival was rate-limited in is the server's own, so the
    /// gate both instruments consult lets the record through.
    #[test]
    fn a_clean_window_publishes() {
        assert!(
            !rate_limited_observed(),
            "nothing in this process observed a 429"
        );
        assert_eq!(refuse_rate_limited_record("perf"), Ok(()));
        assert_eq!(refuse_rate_limited_record("stress"), Ok(()));
    }

    /// One rate-limited arrival withholds the record from both instruments,
    /// and the refusal names the status the operator has to clear.
    #[test]
    fn a_rate_limited_window_is_never_published() {
        note_rate_limited();
        assert!(rate_limited_observed(), "the 429 observation did not latch");

        let perf = refuse_rate_limited_record("perf")
            .expect_err("a latched 429 withholds the measured record");
        assert!(perf.starts_with("perf: "), "{perf}");
        assert!(perf.contains("429"), "{perf}");

        let stress = refuse_rate_limited_record("stress")
            .expect_err("a latched 429 withholds the stress record");
        assert!(stress.starts_with("stress: "), "{stress}");
    }
}