ic_backup/model/attempt_journal/observation/
mod.rs1use super::{AttemptAuthorityRecord, AttemptJournalRecord};
3use crate::model::artifacts::ArtifactChecksumRecord;
4use thiserror::Error;
5
6#[derive(Debug)]
7pub(crate) struct ObservationReservation {
8 pub authority: AttemptAuthorityRecord,
9 pub mutation_attempt: u32,
10 pub observation_attempt: u32,
11 pub request: ArtifactChecksumRecord,
12}
13
14fn pending_attempts(
16 journal: &AttemptJournalRecord,
17) -> Result<(u32, u32), ObservationReservationError> {
18 Ok((
19 journal
20 .pending_mutation()
21 .ok_or(ObservationReservationError::NoPendingMutation)?,
22 journal
23 .pending_observation()
24 .ok_or(ObservationReservationError::NoPendingObservation)?,
25 ))
26}
27
28impl ObservationReservation {
29 pub(crate) fn new(
30 authority: AttemptAuthorityRecord,
31 journal: &AttemptJournalRecord,
32 request: ArtifactChecksumRecord,
33 ) -> Result<Self, ObservationReservationError> {
34 let (mutation_attempt, observation_attempt) = pending_attempts(journal)?;
35 let reservation = Self {
36 authority,
37 mutation_attempt,
38 observation_attempt,
39 request,
40 };
41 reservation.validate(journal)?;
42 Ok(reservation)
43 }
44
45 pub(crate) fn validate(
46 &self,
47 journal: &AttemptJournalRecord,
48 ) -> Result<(), ObservationReservationError> {
49 Self::validate_identity(
50 journal,
51 &self.authority,
52 self.mutation_attempt,
53 self.observation_attempt,
54 self.request.hash(),
55 )
56 }
57
58 pub(crate) fn validate_identity(
59 journal: &AttemptJournalRecord,
60 authority: &AttemptAuthorityRecord,
61 mutation_attempt: u32,
62 observation_attempt: u32,
63 request: &str,
64 ) -> Result<(), ObservationReservationError> {
65 if journal.authority() != authority {
66 return Err(ObservationReservationError::AuthorityMismatch);
67 }
68 if journal.pending_mutation() != Some(mutation_attempt) {
69 return Err(ObservationReservationError::MutationMismatch);
70 }
71 if journal.pending_observation() != Some(observation_attempt) {
72 return Err(ObservationReservationError::ObservationMismatch);
73 }
74 if journal.pending_observation_request() != Some(request) {
75 return Err(ObservationReservationError::RequestMismatch);
76 }
77 Ok(())
78 }
79}
80
81#[derive(Clone, Copy, Debug, Eq, Error, PartialEq)]
83pub enum ObservationReservationError {
84 #[error("original observation authority mismatch")]
86 AuthorityMismatch,
87 #[error("observation requires a pending original mutation")]
89 NoPendingMutation,
90 #[error("observation requires a pending original observation")]
92 NoPendingObservation,
93 #[error("original observation mutation mismatch")]
95 MutationMismatch,
96 #[error("original observation attempt mismatch")]
98 ObservationMismatch,
99 #[error("original observation request mismatch")]
101 RequestMismatch,
102}