pub use harmos_domain::operations::lifecycle::{Cancel, InstanceState, Status, Watch};
use std::sync::Arc;
use crate::MemorySize;
use crate::operations::{Context, Lane, Operation, OperationInstanceId, OperationManager, Response, StreamOutput};
use crate::{Error, Result};
pub struct Catalog;
pub struct Reporting;
pub struct Cancelling;
pub struct Watching;
impl Catalog {
pub fn register(operations: &OperationManager, owner: impl Into<String>, lane: impl Lane + Copy) -> Result<()> {
let owner = owner.into();
operations.register_wire_operation::<Reporting>(owner.clone(), lane, Arc::new(()))?;
operations.register_wire_operation::<Cancelling>(owner.clone(), lane, Arc::new(()))?;
operations.register_wire_operation::<Watching>(owner, lane, Arc::new(()))
}
}
impl Operation for Reporting {
type Declaration = Status;
type Resources = ();
type Error = Error;
type Context<'a> = Context<'a>;
type Endpoints = ();
async fn initialize<'ctx>(_: Arc<()>, _: Self::Context<'ctx>) -> Result<Self> {
Ok(Self)
}
async fn run<'ctx>(
&mut self, context: Self::Context<'ctx>, request: &mut Status, _: &mut Self::Endpoints,
) -> Result<Response<InstanceState>> {
let id = OperationInstanceId::new(request.instance);
let instance = context.owned_instance(id).ok_or_else(|| unknown(id))?;
let state = InstanceState::from(instance.status().portable());
Ok(state.into())
}
}
impl Operation for Cancelling {
type Declaration = Cancel;
type Resources = ();
type Error = Error;
type Context<'a> = Context<'a>;
type Endpoints = ();
async fn initialize<'ctx>(_: Arc<()>, _: Self::Context<'ctx>) -> Result<Self> {
Ok(Self)
}
async fn run<'ctx>(
&mut self, context: Self::Context<'ctx>, request: &mut Cancel, _: &mut Self::Endpoints,
) -> Result<Response<InstanceState>> {
let id = OperationInstanceId::new(request.instance);
let instance = context.owned_instance(id).ok_or_else(|| unknown(id))?;
instance.cancel();
let state = InstanceState::from(instance.status().portable());
Ok(state.into())
}
}
impl Operation for Watching {
type Declaration = Watch;
type Resources = ();
type Error = Error;
type Context<'a> = Context<'a>;
type Endpoints = StreamOutput<InstanceState>;
async fn initialize<'ctx>(_: Arc<()>, _: Self::Context<'ctx>) -> Result<Self> {
Ok(Self)
}
async fn run<'ctx>(
&mut self, context: Self::Context<'ctx>, request: &mut Watch, output: &mut Self::Endpoints,
) -> Result<Response<InstanceState>> {
let id = OperationInstanceId::new(request.instance);
let instance = context.owned_instance(id).ok_or_else(|| unknown(id))?;
let mut changes = instance.settlement();
drop(instance);
loop {
let status = changes.borrow_and_update().portable();
let state = InstanceState::from(status);
output.send_with(state.memory_size(), || Ok(state.clone())).await?;
if status.is_settled() {
return Ok(state.into());
}
if changes.changed().await.is_err() {
return Ok(state.into());
}
}
}
}
fn unknown(id: OperationInstanceId) -> Error {
Error::NotRegistered { domain: "operation instance", name: id.to_string() }
}