swactor/crates/ci/src/provisioner.rs
Zachery Aaron Shores-Chmielewski ee31b6623f
Some checks failed
ci/check Job 'check' failed: command exited with code 101 [stderr] | |_^ [stderr] | [stderr] = note: the lang item is first defined in crate `std` (which `ed25519_dalek` depends on) [stderr] = note: first definition in `std` loaded from /home/z...
ci/clippy Job 'clippy' failed: command exited with code 101 [stderr] help: try adding this [stderr] | [stderr] 157 + impl Default for TransportRouter { [stderr] 158 + fn default() -> Self { [stderr] 159 + Self::new() [stderr] 160 + } [st...
ci/ci Pipeline 'ci' failure
feat: mvp ci workflow (#42)
Not working too well and difficult to track, but has a skeleton there to work from.
Co-authored-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
Co-committed-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-02-16 15:57:55 +00:00

86 lines
3 KiB
Rust

//! Provisioner actor: manages spot instance lifecycle via pluggable provider scripts.
//!
//! In real deployment, runs on the developer's laptop and calls cloud provider APIs.
//! In simulation, provisions are driven by the simulation harness.
use swactor::actor::{ActorAddress, ActorInterface, Ctx};
use crate::coordinator::CoordinatorMsg;
use crate::{
InstanceReady, ProvisionError, ProvisionRequest, ProvisionResponse, TerminateRequest,
};
/// Messages the Provisioner can receive.
#[derive(Debug, Clone)]
pub enum ProvisionerMsg {
/// Request to provision a new spot instance.
Provision(ProvisionRequest),
/// Request to terminate a spot instance.
Terminate(TerminateRequest),
/// Simulated: provisioning result delivered asynchronously.
SimProvisionResult {
request: ProvisionRequest,
result: Result<InstanceReady, ProvisionError>,
},
}
/// Provisioner actor state.
///
/// In real deployment, this would invoke provider scripts.
/// In simulation, the sim harness controls provision outcomes.
pub struct Provisioner {
coordinator_addr: ActorAddress,
/// Active instances tracked for cleanup.
active_instances: Vec<String>,
}
impl Provisioner {
pub fn new(coordinator_addr: ActorAddress) -> Self {
Self {
coordinator_addr,
active_instances: Vec::new(),
}
}
pub fn active_instances(&self) -> &[String] {
&self.active_instances
}
}
impl ActorInterface for Provisioner {
type Incoming = ProvisionerMsg;
type Response = ();
fn handle(&mut self, ctx: &Ctx, msg: ProvisionerMsg) {
match msg {
ProvisionerMsg::Provision(_request) => {
// In real deployment: invoke provider script, await result.
// In simulation: the sim harness sends SimProvisionResult.
}
ProvisionerMsg::Terminate(request) => {
self.active_instances.retain(|id| id != &request.instance_id);
// In real deployment: invoke provider destroy script.
// In simulation: just track the termination.
let _ = ctx.send(
self.coordinator_addr,
CoordinatorMsg::ProvisionResponse(ProvisionResponse {
job_id: request.job_id.clone(),
result: Err(ProvisionError::NoCapacity), // placeholder, terminate doesn't need response
}),
);
}
ProvisionerMsg::SimProvisionResult { request, result } => {
if let Ok(ref instance) = result {
self.active_instances.push(instance.instance_id.clone());
}
let _ = ctx.send(
self.coordinator_addr,
CoordinatorMsg::ProvisionResponse(ProvisionResponse {
job_id: request.job_id,
result,
}),
);
}
}
}
}