use super::*; use sprinklers_actors::{program_runner::Error, state_manager::StateError}; use sprinklers_core::model::{ProgramId, ProgramRef, ProgramUpdateData}; use eyre::WrapErr; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RunProgramRequest { program_id: ProgramId, } impl IRequest for RunProgramRequest { type Response = ResponseMessage; fn exec(self, ctx: &mut RequestContext) -> RequestFuture { let mut program_runner = ctx.program_runner.clone(); let program_id = self.program_id; Box::pin(async move { match program_runner.run_program_id(program_id).await { Ok(program) => Ok(ResponseMessage::new(format!( "running program '{}'", program.name ))), Err(e @ Error::InvalidProgramId(_)) => Err(RequestError::with_name( ErrorCode::NoSuchProgram, e, "program", )), Err(e) => Err(e).wrap_err("could not run program")?, } }) } } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CancelProgramRequest { program_id: ProgramId, } impl IRequest for CancelProgramRequest { type Response = ResponseMessage; fn exec(self, ctx: &mut RequestContext) -> RequestFuture { let mut program_runner = ctx.program_runner.clone(); let program_id = self.program_id; Box::pin(async move { let cancelled = program_runner .cancel_program(program_id) .await .wrap_err("could not run cancel program")?; match cancelled { Some(program) => Ok(ResponseMessage::new(format!( "program '{}' cancelled", program.name ))), None => Err(RequestError::with_name( ErrorCode::NoSuchProgram, "program was not running", "program", )), } }) } } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpdateProgramRequest { program_id: ProgramId, data: ProgramUpdateData, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct UpdateProgramResponse { message: String, data: ProgramRef, } impl IRequest for UpdateProgramRequest { type Response = UpdateProgramResponse; fn exec(self, ctx: &mut RequestContext) -> RequestFuture { let mut state_manager = ctx.state_manager.clone(); Box::pin(async move { let new_program = state_manager .update_program(self.program_id, self.data) .await .map_err(|err| match err { e @ StateError::NoSuchProgram(_) => RequestError::with_name_and_cause( ErrorCode::NoSuchProgram, "could not update program", "program", e, ), e => RequestError::from(eyre::Report::from(e)), })?; Ok(UpdateProgramResponse { message: format!("updated program '{}'", new_program.name), data: new_program, }) }) } }