trellis_core/
host_status.rs1use crate::{ErrorCategory, ResourceKey, Revision, ScopeId};
2
3#[derive(Clone, Debug, Eq, PartialEq)]
5pub enum HostResourceOutcome {
6 Unknown,
8 Open,
10 Failed(String),
12 Closed,
14 Unsupported(String),
16}
17
18impl HostResourceOutcome {
19 pub const fn category(&self) -> ErrorCategory {
21 ErrorCategory::HostResourceStatus
22 }
23}
24
25#[derive(Clone, Debug, Eq, PartialEq)]
27pub struct HostResourceStatus<S = HostResourceOutcome> {
28 pub resource_key: ResourceKey,
30 pub scope: ScopeId,
32 pub command_revision: Revision,
34 pub status_revision: Revision,
36 pub status: S,
38}
39
40impl<S> HostResourceStatus<S> {
41 pub fn new(
43 resource_key: ResourceKey,
44 scope: ScopeId,
45 command_revision: Revision,
46 status_revision: Revision,
47 status: S,
48 ) -> Self {
49 Self {
50 resource_key,
51 scope,
52 command_revision,
53 status_revision,
54 status,
55 }
56 }
57
58 pub const fn category(&self) -> ErrorCategory {
60 ErrorCategory::HostResourceStatus
61 }
62
63 pub fn map_status<T>(self, map: impl FnOnce(S) -> T) -> HostResourceStatus<T> {
65 HostResourceStatus {
66 resource_key: self.resource_key,
67 scope: self.scope,
68 command_revision: self.command_revision,
69 status_revision: self.status_revision,
70 status: map(self.status),
71 }
72 }
73}
74
75#[derive(Copy, Clone, Debug, Eq, PartialEq)]
77pub enum HostStatusClass {
78 Current,
80 Duplicate,
82 Stale,
84 Future,
86 Late,
88}
89
90#[derive(Copy, Clone, Debug, Eq, PartialEq)]
92pub struct HostResourceCommandState {
93 pub scope: ScopeId,
95 pub command_revision: Revision,
97 pub resource_is_live: bool,
99 pub scope_owns_resource: bool,
101}
102
103pub fn classify_host_resource_status(
105 status: &HostResourceStatus,
106 state: Option<HostResourceCommandState>,
107 duplicate: bool,
108) -> HostStatusClass {
109 let Some(state) = state else {
110 return HostStatusClass::Late;
111 };
112
113 if !state.resource_is_live {
114 if matches!(status.status, HostResourceOutcome::Closed) && state.scope == status.scope {
115 return classify_revision(status.command_revision, state.command_revision, duplicate);
116 }
117 return HostStatusClass::Late;
118 }
119
120 if !state.scope_owns_resource {
121 return HostStatusClass::Late;
122 }
123
124 classify_revision(status.command_revision, state.command_revision, duplicate)
125}
126
127fn classify_revision(
128 status_revision: Revision,
129 command_revision: Revision,
130 duplicate: bool,
131) -> HostStatusClass {
132 if status_revision < command_revision {
133 HostStatusClass::Stale
134 } else if status_revision > command_revision {
135 HostStatusClass::Future
136 } else if duplicate {
137 HostStatusClass::Duplicate
138 } else {
139 HostStatusClass::Current
140 }
141}