use super::{ApplicationIngressError, ApplicationIngressPayload};
use crate::model::attempt_journal::MutationReservation;
use crate::model::attempt_journal::MutationReservationError as Reservation;
use crate::model::attempt_journal::ObservationReservation;
use crate::model::{
attempt_journal::{AttemptAuthorityRecord, AttemptJournalRecord},
operation_plan::OperationPlanRecord,
};
#[derive(Debug)]
pub struct ApplicationMutationRequest<'a> {
plan: &'a OperationPlanRecord,
payload: &'a ApplicationIngressPayload,
reservation: MutationReservation,
}
impl<'a> ApplicationMutationRequest<'a> {
pub fn new(
plan: &'a OperationPlanRecord,
sequence: u64,
journal: &AttemptJournalRecord,
payload: &'a ApplicationIngressPayload,
) -> Result<Self, ApplicationIngressError> {
let authority = authority(plan, sequence, journal)?;
payload.validate_mutation_binding(authority.binding())?;
let reservation = MutationReservation::new(authority, journal)?;
Ok(Self {
plan,
payload,
reservation,
})
}
#[must_use]
pub const fn plan(&self) -> &OperationPlanRecord {
self.plan
}
#[must_use]
pub const fn payload(&self) -> &ApplicationIngressPayload {
self.payload
}
#[must_use]
pub const fn authority(&self) -> &AttemptAuthorityRecord {
&self.reservation.authority
}
#[must_use]
pub const fn mutation_attempt(&self) -> u32 {
self.reservation.mutation_attempt
}
pub fn validate_journal(
&self,
journal: &AttemptJournalRecord,
) -> Result<(), ApplicationIngressError> {
self.reservation.validate(journal).map_err(Into::into)
}
}
#[derive(Debug)]
pub struct ApplicationObservationRequest<'a> {
plan: &'a OperationPlanRecord,
payload: &'a ApplicationIngressPayload,
reservation: ObservationReservation,
}
impl<'a> ApplicationObservationRequest<'a> {
pub fn new(
plan: &'a OperationPlanRecord,
sequence: u64,
journal: &AttemptJournalRecord,
payload: &'a ApplicationIngressPayload,
) -> Result<Self, ApplicationIngressError> {
let authority = authority(plan, sequence, journal)?;
payload.validate_observation_binding(authority.binding())?;
let reservation = ObservationReservation::new(authority, journal, payload.digest())
.map_err(crate::model::ic_observation::IcObservationRequestError::from)?;
Ok(Self {
plan,
payload,
reservation,
})
}
#[must_use]
pub const fn plan(&self) -> &OperationPlanRecord {
self.plan
}
#[must_use]
pub const fn payload(&self) -> &ApplicationIngressPayload {
self.payload
}
#[must_use]
pub const fn authority(&self) -> &AttemptAuthorityRecord {
&self.reservation.authority
}
#[must_use]
pub const fn mutation_attempt(&self) -> u32 {
self.reservation.mutation_attempt
}
#[must_use]
pub const fn observation_attempt(&self) -> u32 {
self.reservation.observation_attempt
}
pub fn validate_journal(
&self,
journal: &AttemptJournalRecord,
) -> Result<(), ApplicationIngressError> {
self.reservation
.validate(journal)
.map_err(crate::model::ic_observation::IcObservationRequestError::from)?;
Ok(())
}
}
fn authority(
plan: &OperationPlanRecord,
sequence: u64,
journal: &AttemptJournalRecord,
) -> Result<AttemptAuthorityRecord, ApplicationIngressError> {
let authority = plan.attempt_authority(sequence)?;
if journal.authority() != &authority {
return Err(ApplicationIngressError::AuthorityMismatch);
}
Ok(authority)
}
impl From<crate::model::attempt_journal::MutationReservationError> for ApplicationIngressError {
fn from(error: crate::model::attempt_journal::MutationReservationError) -> Self {
match error {
Reservation::NoPendingMutation => Self::NoPendingMutation,
Reservation::AuthorityMismatch => Self::AuthorityMismatch,
Reservation::MutationMismatch => Self::MutationMismatch,
Reservation::ObservationPending => Self::ObservationPending,
}
}
}