ic_backup/model/application_ingress/request/
mod.rs1use super::{ApplicationIngressError, ApplicationIngressPayload};
4use crate::model::{
5 attempt_journal::{AttemptAuthorityRecord, AttemptJournalRecord},
6 ic_observation::ObservationReservation,
7 operation_plan::OperationPlanRecord,
8};
9
10#[derive(Debug)]
15pub struct ApplicationMutationRequest<'a> {
16 plan: &'a OperationPlanRecord,
17 payload: &'a ApplicationIngressPayload,
18 authority: AttemptAuthorityRecord,
19 mutation_attempt: u32,
20}
21impl<'a> ApplicationMutationRequest<'a> {
22 pub fn new(
26 plan: &'a OperationPlanRecord,
27 sequence: u64,
28 journal: &AttemptJournalRecord,
29 payload: &'a ApplicationIngressPayload,
30 ) -> Result<Self, ApplicationIngressError> {
31 let authority = authority(plan, sequence, journal)?;
32 payload.validate_mutation_binding(authority.binding())?;
33 let mutation_attempt = journal
34 .pending_mutation()
35 .ok_or(ApplicationIngressError::NoPendingMutation)?;
36 let request = Self {
37 plan,
38 payload,
39 authority,
40 mutation_attempt,
41 };
42 request.validate_journal(journal)?;
43 Ok(request)
44 }
45 #[must_use]
47 pub const fn plan(&self) -> &OperationPlanRecord {
48 self.plan
49 }
50 #[must_use]
52 pub const fn payload(&self) -> &ApplicationIngressPayload {
53 self.payload
54 }
55 #[must_use]
57 pub const fn authority(&self) -> &AttemptAuthorityRecord {
58 &self.authority
59 }
60 #[must_use]
62 pub const fn mutation_attempt(&self) -> u32 {
63 self.mutation_attempt
64 }
65 pub fn validate_journal(
69 &self,
70 journal: &AttemptJournalRecord,
71 ) -> Result<(), ApplicationIngressError> {
72 journal.validate_pending_mutation(
73 &self.authority,
74 self.mutation_attempt,
75 ApplicationIngressError::AuthorityMismatch,
76 ApplicationIngressError::MutationMismatch,
77 ApplicationIngressError::ObservationPending,
78 )
79 }
80}
81
82#[derive(Debug)]
87pub struct ApplicationObservationRequest<'a> {
88 plan: &'a OperationPlanRecord,
89 payload: &'a ApplicationIngressPayload,
90 reservation: ObservationReservation,
91}
92impl<'a> ApplicationObservationRequest<'a> {
93 pub fn new(
97 plan: &'a OperationPlanRecord,
98 sequence: u64,
99 journal: &AttemptJournalRecord,
100 payload: &'a ApplicationIngressPayload,
101 ) -> Result<Self, ApplicationIngressError> {
102 let authority = authority(plan, sequence, journal)?;
103 payload.validate_observation_binding(authority.binding())?;
104 let reservation = ObservationReservation::new(authority, journal, payload.digest())?;
105 Ok(Self {
106 plan,
107 payload,
108 reservation,
109 })
110 }
111 #[must_use]
113 pub const fn plan(&self) -> &OperationPlanRecord {
114 self.plan
115 }
116 #[must_use]
118 pub const fn payload(&self) -> &ApplicationIngressPayload {
119 self.payload
120 }
121 #[must_use]
123 pub const fn authority(&self) -> &AttemptAuthorityRecord {
124 &self.reservation.authority
125 }
126 #[must_use]
128 pub const fn mutation_attempt(&self) -> u32 {
129 self.reservation.mutation_attempt
130 }
131 #[must_use]
133 pub const fn observation_attempt(&self) -> u32 {
134 self.reservation.observation_attempt
135 }
136 pub fn validate_journal(
140 &self,
141 journal: &AttemptJournalRecord,
142 ) -> Result<(), ApplicationIngressError> {
143 self.reservation.validate(journal)?;
144 Ok(())
145 }
146}
147
148fn authority(
149 plan: &OperationPlanRecord,
150 sequence: u64,
151 journal: &AttemptJournalRecord,
152) -> Result<AttemptAuthorityRecord, ApplicationIngressError> {
153 let authority = plan.attempt_authority(sequence)?;
154 if journal.authority() != &authority {
155 return Err(ApplicationIngressError::AuthorityMismatch);
156 }
157 Ok(authority)
158}