Skip to content

Commit 2a810ee

Browse files
committed
severity trait, wildcard enum footgun
1 parent 80bb033 commit 2a810ee

File tree

4 files changed

+65
-116
lines changed

4 files changed

+65
-116
lines changed

extension/src/lambda_request_error.rs

Lines changed: 31 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use crate::messages::ExitReason;
1+
use crate::{messages::ExitReason, prelude::*};
22

3-
#[derive(Debug, PartialEq)]
3+
#[derive(Debug, PartialEq, Copy, Clone)]
44
pub enum LambdaRequestError {
55
RouterLambdaInvokeInvalid,
66
RouterUnreachable,
@@ -64,53 +64,22 @@ impl From<&LambdaRequestError> for ExitReason {
6464

6565
impl LambdaRequestError {
6666
pub fn is_fatal(&self) -> bool {
67-
use LambdaRequestError::*;
68-
69-
let fatal_errors = [
70-
// Add other fatal errors here
71-
AppConnectionUnreachable,
72-
];
73-
74-
fatal_errors.contains(self)
75-
}
76-
77-
pub fn worse(self, other: Self) -> Self {
78-
use LambdaRequestError::*;
79-
80-
let ordered_reasons = [
81-
RouterLambdaInvokeInvalid,
82-
RouterUnreachable,
83-
RouterConnectionError,
84-
AppConnectionUnreachable,
85-
AppConnectionError,
86-
ChannelErrorOther,
87-
];
88-
89-
for reason in ordered_reasons {
90-
if self == reason || other == reason {
91-
return reason;
92-
}
93-
}
94-
95-
self // If no match is found, return the current value
67+
// Add other fatal errors to the match pattern. For example:
68+
// matches!(self, Self::Variant1 | Self::Variant2)
69+
matches!(self, Self::AppConnectionUnreachable)
9670
}
71+
}
9772

98-
// This function will cause a compile-time error if a new variant is added to the enum
99-
// but not added to the match expression.
100-
#[allow(dead_code)]
101-
fn ensure_all_variants_handled(variant: Self) {
102-
use LambdaRequestError::*;
103-
104-
match variant {
105-
// HEY - If you add here you need to add to the `worse` function array above
106-
RouterLambdaInvokeInvalid => {}
107-
RouterUnreachable => {}
108-
RouterConnectionError => {}
109-
AppConnectionUnreachable => {}
110-
AppConnectionError => {}
111-
ChannelErrorOther => {}
73+
impl Severity for LambdaRequestError {
74+
fn severity(&self) -> usize {
75+
match self {
76+
Self::RouterLambdaInvokeInvalid => 0,
77+
Self::RouterUnreachable => 1,
78+
Self::RouterConnectionError => 2,
79+
Self::AppConnectionUnreachable => 3,
80+
Self::AppConnectionError => 4,
81+
Self::ChannelErrorOther => 5,
11282
}
113-
// HEY - If you add here you need to add to the `worse` function array above
11483
}
11584
}
11685

@@ -166,46 +135,46 @@ mod tests {
166135

167136
#[test]
168137
fn test_worse() {
169-
use LambdaRequestError::*;
138+
use LambdaRequestError as E;
170139

171140
// Test that RouterUnreachable is considered worse than AppConnectionError
172-
let error1 = RouterUnreachable;
173-
let error2 = AppConnectionError;
174-
assert_eq!(error1.worse(error2), RouterUnreachable);
141+
let error1 = E::RouterUnreachable;
142+
let error2 = E::AppConnectionError;
143+
assert_eq!(error1.worse(error2), E::RouterUnreachable);
175144

176145
// Test that AppConnectionError is considered worse than ChannelErrorOther
177-
let error1 = AppConnectionError;
178-
let error2 = ChannelErrorOther;
179-
assert_eq!(error1.worse(error2), AppConnectionError);
146+
let error1 = E::AppConnectionError;
147+
let error2 = E::ChannelErrorOther;
148+
assert_eq!(error1.worse(error2), E::AppConnectionError);
180149

181150
// Test that when both errors are the same, that error is returned
182-
let error1 = ChannelErrorOther;
183-
let error2 = ChannelErrorOther;
184-
assert_eq!(error1.worse(error2), ChannelErrorOther);
151+
let error1 = E::ChannelErrorOther;
152+
let error2 = E::ChannelErrorOther;
153+
assert_eq!(error1.worse(error2), E::ChannelErrorOther);
185154
}
186155

187156
#[test]
188157
fn test_is_fatal() {
189-
use LambdaRequestError::*;
158+
use LambdaRequestError as E;
190159

191160
// Test that AppConnectionUnreachable is considered fatal
192-
let error = AppConnectionUnreachable;
161+
let error = E::AppConnectionUnreachable;
193162
assert!(error.is_fatal());
194163

195164
// Test that RouterUnreachable is not considered fatal
196-
let error = RouterUnreachable;
165+
let error = E::RouterUnreachable;
197166
assert!(!error.is_fatal());
198167

199168
// Test that RouterConnectionError is not considered fatal
200-
let error = RouterConnectionError;
169+
let error = E::RouterConnectionError;
201170
assert!(!error.is_fatal());
202171

203172
// Test that AppConnectionError is not considered fatal
204-
let error = AppConnectionError;
173+
let error = E::AppConnectionError;
205174
assert!(!error.is_fatal());
206175

207176
// Test that ChannelErrorOther is not considered fatal
208-
let error = ChannelErrorOther;
177+
let error = E::ChannelErrorOther;
209178
assert!(!error.is_fatal());
210179
}
211180
}

extension/src/messages.rs

Lines changed: 17 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -70,60 +70,24 @@ pub enum ExitReason {
7070
ChannelErrorOther,
7171
}
7272

73-
impl ExitReason {
74-
pub fn worse(self, other: Self) -> Self {
75-
use ExitReason::*;
76-
77-
let ordered_reasons = [
78-
RouterLambdaInvokeInvalid,
79-
RouterUnreachable,
80-
RouterConnectionError,
81-
ChannelErrorOther,
82-
AppConnectionError,
83-
AppConnectionClosed,
84-
RouterStatus5xx,
85-
RouterStatus4xx,
86-
RouterStatusOther,
87-
RouterGoAway,
88-
SelfLastActive,
89-
SelfDeadline,
90-
SelfStaleRequest,
91-
SelfInitOnly,
92-
];
93-
94-
for reason in ordered_reasons {
95-
if self == reason || other == reason {
96-
return reason;
97-
}
98-
}
99-
100-
self // If no match is found, return the current value
101-
}
102-
103-
// This function will cause a compile-time error if a new variant is added to the enum
104-
// but not added to the match expression.
105-
#[allow(dead_code)]
106-
fn ensure_all_variants_handled(variant: Self) {
107-
use ExitReason::*;
108-
109-
match variant {
110-
// HEY - If you add here you need to add to the `worse` function array above
111-
RouterLambdaInvokeInvalid => {}
112-
RouterUnreachable => {}
113-
RouterConnectionError => {}
114-
ChannelErrorOther => {}
115-
AppConnectionError => {}
116-
AppConnectionClosed => {}
117-
RouterStatus5xx => {}
118-
RouterStatus4xx => {}
119-
RouterStatusOther => {}
120-
RouterGoAway => {}
121-
SelfLastActive => {}
122-
SelfDeadline => {}
123-
SelfStaleRequest => {}
124-
SelfInitOnly => {}
73+
impl Severity for ExitReason {
74+
fn severity(&self) -> usize {
75+
match self {
76+
Self::RouterLambdaInvokeInvalid => 0,
77+
Self::RouterUnreachable => 1,
78+
Self::RouterConnectionError => 2,
79+
Self::ChannelErrorOther => 3,
80+
Self::AppConnectionError => 4,
81+
Self::AppConnectionClosed => 5,
82+
Self::RouterStatus5xx => 6,
83+
Self::RouterStatus4xx => 7,
84+
Self::RouterStatusOther => 8,
85+
Self::RouterGoAway => 9,
86+
Self::SelfLastActive => 10,
87+
Self::SelfDeadline => 11,
88+
Self::SelfStaleRequest => 12,
89+
Self::SelfInitOnly => 13,
12590
}
126-
// HEY - If you add here you need to add to the `worse` function array above
12791
}
12892
}
12993

extension/src/prelude.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,16 @@ pub use anyhow::{Context, Error, Result};
44
pub type LambdaId = Arc<str>;
55
pub type PoolId = Arc<str>;
66
pub type ChannelId = Arc<str>;
7+
8+
pub trait Severity: Sized {
9+
/// Lower values represent higher severity with zero being the highest (akin to SEV0, SEV1, etc).
10+
fn severity(&self) -> usize;
11+
12+
/// Compares two [`Severity`]s, returning the highest.
13+
fn worse(self, other: Self) -> Self {
14+
if self.severity() > other.severity() {
15+
return other;
16+
}
17+
self
18+
}
19+
}

extension/tests/messages.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#[cfg(test)]
22
mod tests {
33
use chrono::{DateTime, Utc};
4-
use extension::messages::{ExitReason, ValidationError, WaiterRequest, WaiterResponse};
4+
use extension::{
5+
messages::{ExitReason, ValidationError, WaiterRequest, WaiterResponse},
6+
prelude::*,
7+
};
58
use hyper::Uri;
69
use serde_json::json;
710

0 commit comments

Comments
 (0)