1 use self::Kind::*; 2 use std::error; 3 use std::fmt; 4 5 /// Errors encountered by the timer implementation. 6 /// 7 /// Currently, there are two different errors that can occur: 8 /// 9 /// * `shutdown` occurs when a timer operation is attempted, but the timer 10 /// instance has been dropped. In this case, the operation will never be able 11 /// to complete and the `shutdown` error is returned. This is a permanent 12 /// error, i.e., once this error is observed, timer operations will never 13 /// succeed in the future. 14 /// 15 /// * `at_capacity` occurs when a timer operation is attempted, but the timer 16 /// instance is currently handling its maximum number of outstanding delays. 17 /// In this case, the operation is not able to be performed at the current 18 /// moment, and `at_capacity` is returned. This is a transient error, i.e., at 19 /// some point in the future, if the operation is attempted again, it might 20 /// succeed. Callers that observe this error should attempt to [shed load]. One 21 /// way to do this would be dropping the future that issued the timer operation. 22 /// 23 /// [shed load]: https://en.wikipedia.org/wiki/Load_Shedding 24 #[derive(Debug)] 25 pub struct Error(Kind); 26 27 #[derive(Debug, Clone, Copy)] 28 #[repr(u8)] 29 enum Kind { 30 Shutdown = 1, 31 AtCapacity = 2, 32 Invalid = 3, 33 } 34 35 impl Error { 36 /// Creates an error representing a shutdown timer. shutdown() -> Error37 pub fn shutdown() -> Error { 38 Error(Shutdown) 39 } 40 41 /// Returns `true` if the error was caused by the timer being shutdown. is_shutdown(&self) -> bool42 pub fn is_shutdown(&self) -> bool { 43 match self.0 { 44 Kind::Shutdown => true, 45 _ => false, 46 } 47 } 48 49 /// Creates an error representing a timer at capacity. at_capacity() -> Error50 pub fn at_capacity() -> Error { 51 Error(AtCapacity) 52 } 53 54 /// Returns `true` if the error was caused by the timer being at capacity. is_at_capacity(&self) -> bool55 pub fn is_at_capacity(&self) -> bool { 56 match self.0 { 57 Kind::AtCapacity => true, 58 _ => false, 59 } 60 } 61 62 /// Create an error representing a misconfigured timer. invalid() -> Error63 pub fn invalid() -> Error { 64 Error(Invalid) 65 } 66 67 /// Returns `true` if the error was caused by the timer being misconfigured. is_invalid(&self) -> bool68 pub fn is_invalid(&self) -> bool { 69 match self.0 { 70 Kind::Invalid => true, 71 _ => false, 72 } 73 } 74 as_u8(&self) -> u875 pub(crate) fn as_u8(&self) -> u8 { 76 self.0 as u8 77 } 78 from_u8(n: u8) -> Self79 pub(crate) fn from_u8(n: u8) -> Self { 80 Error(match n { 81 1 => Shutdown, 82 2 => AtCapacity, 83 3 => Invalid, 84 _ => panic!("u8 does not correspond to any time error variant"), 85 }) 86 } 87 } 88 89 impl error::Error for Error {} 90 91 impl fmt::Display for Error { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result92 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 93 use self::Kind::*; 94 let descr = match self.0 { 95 Shutdown => "the timer is shutdown, must be called from the context of Tokio runtime", 96 AtCapacity => "timer is at capacity and cannot create a new entry", 97 Invalid => "timer duration exceeds maximum duration", 98 }; 99 write!(fmt, "{}", descr) 100 } 101 } 102