open-standards/eoc/eoc-rs/crates/eoc-distributed/tests/work_stealing.rs
Transaction Science 6ea90afbed ingest wave A4: 3 crates · smart-byte-atproto + op-openbanking + eoc-distributed
Smart Byte (1 crate, 2127 LOC, 35 tests)
  smart-byte-atproto    ATProto (Bluesky federation) adapter.
                        PLC + did:web resolution; XRPC client; CARv1 encode/decode
                        with CIDv1 (dag-cbor + raw, SHA-256); sketch MST with
                        order-independent BLAKE3 root; Repo + UnsignedCommit /
                        SignedCommit (Ed25519 over CBOR); firehose transport
                        trait + in-memory impl; AT URI ↔ smart-byte AID bridge
                        with SAID commitment.

OpenPay (1 crate, 2397 LOC, 44 tests)
  op-openbanking        UK OBIE R/W v3.1.10/3.1.11, Berlin Group NextGenPSD2
                        XS2A v1.3.13, STET PSD2 v1.7, Australia CDR Banking v1.31,
                        FDX v5/v6, SGFinDex shapes. AISP / PISP / PIIS / VRP
                        traits. FAPI 1.0 Advanced (PS256/ES256, mTLS, RFC 8705
                        certificate binding, JWK registration). Operators wire
                        their own JWS signer + HTTP transport — keeps the crate
                        KMS-agnostic.

EOC (1 crate, 2179 LOC, 32 tests)
  eoc-distributed       Distributed-inference scheduling. Worker trait with
                        Capability + Accelerator (CPU/GPU/TPU/NPU/Mixed) +
                        Load.busyness()/projected_micro_joules()/projected_g_co2e().
                        RoundRobin / LeastBusy / LatencyWeighted / JouleWeighted
                        (default) / CarbonWeighted routers. Work-stealing
                        scheduler. vLLM-style continuous batching with KV-block
                        budget. Ray-Serve-style auto-scaler with cooldown.
                        KV-cache-aware sticky-session routing.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-24 12:22:09 -04:00

134 lines
3.5 KiB
Rust

//! Work-stealing scheduler balances load between heterogeneous workers.
use eoc_distributed::{
Accelerator, Capability, InMemoryWorker, Load, WorkItem, WorkStealingScheduler, Worker,
};
fn cpu(id: &str, micro_j: u32) -> InMemoryWorker {
InMemoryWorker::new(
id,
Capability {
models: vec!["m".into()],
accelerator: Accelerator::Cpu,
max_concurrency: 8,
continuous_batching: false,
paged_kv: false,
zone: "EU-FR".into(),
},
Load {
micro_joules_per_token: micro_j,
..Load::idle()
},
)
}
fn gpu(id: &str, micro_j: u32) -> InMemoryWorker {
InMemoryWorker::new(
id,
Capability {
models: vec!["m".into()],
accelerator: Accelerator::Gpu,
max_concurrency: 16,
continuous_batching: true,
paged_kv: true,
zone: "EU-FR".into(),
},
Load {
micro_joules_per_token: micro_j,
..Load::idle()
},
)
}
#[test]
fn submit_lands_in_lowest_joule_worker() {
let mut s = WorkStealingScheduler::new();
let a = cpu("a", 200);
let b = cpu("b", 50);
let pool: Vec<&dyn Worker> = vec![&a, &b];
s.ensure(&pool);
for i in 0..5 {
s.submit(
&pool,
WorkItem {
id: format!("r{i}"),
model: "m".into(),
expected_tokens: 32,
require: None,
locality_hint: None,
},
)
.expect("ok");
}
assert_eq!(s.depth("b"), 5);
assert_eq!(s.depth("a"), 0);
}
#[test]
fn idle_worker_steals_from_busy() {
let mut s = WorkStealingScheduler::new();
let a = cpu("a", 100);
let b = cpu("b", 100);
let pool: Vec<&dyn Worker> = vec![&a, &b];
s.ensure(&pool);
// Pile four items directly into a's inbox via repeated submits
// (both are CPU workers with equal joule cost — submit goes to
// whichever min_by sees first; doesn't matter for this test).
for i in 0..4 {
s.submit(
&pool,
WorkItem {
id: format!("r{i}"),
model: "m".into(),
expected_tokens: 16,
require: None,
locality_hint: None,
},
)
.expect("ok");
}
// Find the worker that ended up loaded.
let (loaded, empty) = if s.depth("a") > s.depth("b") {
("a", "b")
} else {
("b", "a")
};
assert!(s.depth(loaded) >= 2);
assert_eq!(s.depth(empty), 0);
let stolen = s.steal(&pool, empty).expect("steal");
assert!(!stolen.is_empty());
assert_eq!(s.depth(empty), 1);
assert_eq!(s.depth(loaded), 3);
}
#[test]
fn capability_filters_block_cross_class_steal() {
let mut s = WorkStealingScheduler::new();
let cpu_a = cpu("cpu-a", 100);
let gpu_b = gpu("gpu-b", 100);
let pool: Vec<&dyn Worker> = vec![&cpu_a, &gpu_b];
s.ensure(&pool);
// Submit a GPU-requiring item; it lands on the GPU worker.
s.submit(
&pool,
WorkItem {
id: "gpu-only".into(),
model: "m".into(),
expected_tokens: 32,
require: Some(Accelerator::Gpu),
locality_hint: None,
},
)
.expect("ok");
assert_eq!(s.depth("gpu-b"), 1);
// CPU worker tries to steal — must fail (returns None).
let stolen = s.steal(&pool, "cpu-a");
assert!(stolen.is_none());
assert_eq!(s.depth("gpu-b"), 1);
assert_eq!(s.depth("cpu-a"), 0);
}