Consolidate Item Spec functions into single trait
azriel91 opened this issue · 0 comments
azriel91 commented
What
Currently ItemSpec
has a number of associated types to split up the logic into different trait implementations.
Consolidating this into the top level ItemSpec
trait should reduce the cognitive load on maintainers for:
- Keeping the data associated types in sync
- Reducing the number of traits to learn and track.
Details
Current traits
pub trait ItemSpec: DynClone {
// Data types
type Error: std::error::Error;
type State: Clone + fmt::Display + Serialize + DeserializeOwned;
type StateDiff: Clone + fmt::Display + Serialize + DeserializeOwned;
// Logic types
type StateCurrentFnSpec: TryFnSpec<Error = Self::Error, Output = Self::State>;
type StateDesiredFnSpec: TryFnSpec<Error = Self::Error, Output = Self::State>;
type StateDiffFnSpec: StateDiffFnSpec<Error = Self::Error, State = Self::State, StateDiff = Self::StateDiff>;
type EnsureOpSpec: EnsureOpSpec<Error = Self::Error, State = Self::State, StateDiff = Self::StateDiff>;
type CleanOpSpec: CleanOpSpec<Error = Self::Error, State = Self::State>;
}
pub trait TryFnSpec {
type Output;
type Data<'op>: Data<'op>
where
Self: 'op;
type Error: std::error::Error;
async fn try_exec(data: Self::Data<'_>) -> Result<Option<Self::Output>, Self::Error>;
async fn exec(data: Self::Data<'_>) -> Result<Self::Output, Self::Error>;
}
pub trait StateDiffFnSpec {
type State: Clone + Serialize + DeserializeOwned;
type StateDiff;
type Data<'op>: Data<'op>
where
Self: 'op;
type Error: std::error::Error;
async fn exec(
data: Self::Data<'_>,
state_current: &Self::State,
state_desired: &Self::State,
) -> Result<Self::StateDiff, Self::Error>;
}
pub trait EnsureOpSpec {
type Error: std::error::Error;
type State: Clone + Serialize + DeserializeOwned;
type StateDiff: Clone + Serialize + DeserializeOwned;
type Data<'op>: Data<'op>
where
Self: 'op;
async fn check(
data: Self::Data<'_>,
state_current: &Self::State,
state_desired: &Self::State,
diff: &Self::StateDiff,
) -> Result<OpCheckStatus, Self::Error>;
async fn exec_dry(
ctx: OpCtx<'_>,
data: Self::Data<'_>,
state_current: &Self::State,
state_desired: &Self::State,
diff: &Self::StateDiff,
) -> Result<Self::State, Self::Error>;
async fn exec(
ctx: OpCtx<'_>,
data: Self::Data<'_>,
state_current: &Self::State,
state_desired: &Self::State,
diff: &Self::StateDiff,
) -> Result<Self::State, Self::Error>;
}
pub trait CleanOpSpec {
type Error: std::error::Error;
type State: Clone + Serialize + DeserializeOwned;
type Data<'op>: Data<'op>
where
Self: 'op;
async fn check(data: Self::Data<'_>, state: &Self::State)
-> Result<OpCheckStatus, Self::Error>;
async fn exec_dry(data: Self::Data<'_>, state: &Self::State) -> Result<(), Self::Error>;
async fn exec(data: Self::Data<'_>, state: &Self::State) -> Result<(), Self::Error>;
}
Consolidated trait
pub trait ItemSpec: DynClone {
// Data types
type Error: std::error::Error;
type State: Clone + fmt::Display + Serialize + DeserializeOwned;
type StateDiff: Clone + fmt::Display + Serialize + DeserializeOwned;
async fn state_current_try(data: Self::Data<'_>) -> Result<Option<Self::Output>, Self::Error>;
async fn state_current(data: Self::Data<'_>) -> Result<Self::Output, Self::Error>;
async fn state_desired_try(data: Self::Data<'_>) -> Result<Option<Self::Output>, Self::Error>;
async fn state_desired(data: Self::Data<'_>) -> Result<Self::Output, Self::Error>;
async fn state_diff(
data: Self::Data<'_>,
state_current: &Self::State,
state_desired: &Self::State,
) -> Result<Self::StateDiff, Self::Error>;
async fn ensure_check(
data: Self::Data<'_>,
state_current: &Self::State,
state_desired: &Self::State,
diff: &Self::StateDiff,
) -> Result<OpCheckStatus, Self::Error>;
async fn ensure_exec_dry(
ctx: OpCtx<'_>,
data: Self::Data<'_>,
state_current: &Self::State,
state_desired: &Self::State,
diff: &Self::StateDiff,
) -> Result<Self::State, Self::Error>;
async fn ensure_exec(
ctx: OpCtx<'_>,
data: Self::Data<'_>,
state_current: &Self::State,
state_desired: &Self::State,
diff: &Self::StateDiff,
) -> Result<Self::State, Self::Error>;
async fn clean_check(data: Self::Data<'_>, state: &Self::State)
-> Result<OpCheckStatus, Self::Error>;
async fn clean_exec_dry(data: Self::Data<'_>, state: &Self::State) -> Result<(), Self::Error>;
async fn clean_exec(data: Self::Data<'_>, state: &Self::State) -> Result<(), Self::Error>;
}
See also #67.