-
Notifications
You must be signed in to change notification settings - Fork 833
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add PrettyDuration, job timeout, job max schedule drift and job retry…
… limit
- Loading branch information
Showing
5 changed files
with
273 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
use std::{ | ||
borrow::Cow, | ||
fmt::{Debug, Display}, | ||
str::FromStr, | ||
time::Duration, | ||
}; | ||
|
||
use schemars::JsonSchema; | ||
use serde::{de::Error, Deserialize, Serialize}; | ||
|
||
#[derive(Clone, Copy, PartialEq, Eq, Hash)] | ||
pub struct PrettyDuration { | ||
unit: DurationUnit, | ||
amount: u64, | ||
} | ||
|
||
#[derive(Clone, Copy, PartialEq, Eq, Hash)] | ||
pub enum DurationUnit { | ||
Seconds, | ||
Minutes, | ||
Hours, | ||
Days, | ||
} | ||
|
||
impl PrettyDuration { | ||
pub fn as_duration(&self) -> Duration { | ||
match self.unit { | ||
DurationUnit::Seconds => Duration::from_secs(self.amount), | ||
DurationUnit::Minutes => Duration::from_secs(self.amount * 60), | ||
DurationUnit::Hours => Duration::from_secs(self.amount * 60 * 60), | ||
DurationUnit::Days => Duration::from_secs(self.amount * 60 * 60 * 24), | ||
} | ||
} | ||
} | ||
|
||
impl Default for PrettyDuration { | ||
fn default() -> Self { | ||
Self { | ||
unit: DurationUnit::Seconds, | ||
amount: 0, | ||
} | ||
} | ||
} | ||
|
||
impl PartialOrd for PrettyDuration { | ||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { | ||
Some(self.cmp(other)) | ||
} | ||
} | ||
|
||
impl Ord for PrettyDuration { | ||
fn cmp(&self, other: &Self) -> std::cmp::Ordering { | ||
self.as_duration().cmp(&other.as_duration()) | ||
} | ||
} | ||
|
||
impl JsonSchema for PrettyDuration { | ||
fn schema_name() -> String { | ||
"PrettyDuration".to_owned() | ||
} | ||
|
||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { | ||
String::json_schema(gen) | ||
} | ||
} | ||
|
||
impl Display for DurationUnit { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
match self { | ||
DurationUnit::Seconds => write!(f, "s"), | ||
DurationUnit::Minutes => write!(f, "m"), | ||
DurationUnit::Hours => write!(f, "h"), | ||
DurationUnit::Days => write!(f, "d"), | ||
} | ||
} | ||
} | ||
|
||
impl FromStr for DurationUnit { | ||
type Err = (); | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
match s { | ||
"s" | "S" => Ok(Self::Seconds), | ||
"m" | "M" => Ok(Self::Minutes), | ||
"h" | "H" => Ok(Self::Hours), | ||
"d" | "D" => Ok(Self::Days), | ||
_ => Err(()), | ||
} | ||
} | ||
} | ||
|
||
impl Display for PrettyDuration { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}{}", self.amount, self.unit) | ||
} | ||
} | ||
|
||
impl Debug for PrettyDuration { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
<Self as Display>::fmt(self, f) | ||
} | ||
} | ||
|
||
impl FromStr for PrettyDuration { | ||
type Err = (); | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
let (amount_str, unit_str) = s.split_at_checked(s.len() - 1).ok_or(())?; | ||
Ok(Self { | ||
unit: unit_str.parse()?, | ||
amount: amount_str.parse().map_err(|_| ())?, | ||
}) | ||
} | ||
} | ||
|
||
impl Serialize for PrettyDuration { | ||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: serde::Serializer, | ||
{ | ||
serializer.serialize_str(&self.to_string()) | ||
} | ||
} | ||
|
||
impl<'de> Deserialize<'de> for PrettyDuration { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: serde::Deserializer<'de>, | ||
{ | ||
let repr: Cow<'de, str> = Cow::deserialize(deserializer)?; | ||
repr.parse() | ||
.map_err(|()| D::Error::custom("Failed to parse value as a duration")) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
pub fn pretty_duration_serialize() { | ||
assert_eq!( | ||
PrettyDuration { | ||
unit: DurationUnit::Seconds, | ||
amount: 1234 | ||
} | ||
.to_string(), | ||
"1234s" | ||
); | ||
assert_eq!( | ||
PrettyDuration { | ||
unit: DurationUnit::Minutes, | ||
amount: 345 | ||
} | ||
.to_string(), | ||
"345m" | ||
); | ||
assert_eq!( | ||
PrettyDuration { | ||
unit: DurationUnit::Hours, | ||
amount: 56 | ||
} | ||
.to_string(), | ||
"56h" | ||
); | ||
assert_eq!( | ||
PrettyDuration { | ||
unit: DurationUnit::Days, | ||
amount: 7 | ||
} | ||
.to_string(), | ||
"7d" | ||
); | ||
} | ||
|
||
#[test] | ||
pub fn pretty_duration_deserialize() { | ||
fn assert_deserializes_to(repr1: &str, repr2: &str, unit: DurationUnit, amount: u64) { | ||
let duration = PrettyDuration { unit, amount }; | ||
assert_eq!(duration, repr1.parse().unwrap()); | ||
assert_eq!(duration, repr2.parse().unwrap()); | ||
} | ||
|
||
assert_deserializes_to("12s", "12S", DurationUnit::Seconds, 12); | ||
assert_deserializes_to("34m", "34M", DurationUnit::Minutes, 34); | ||
assert_deserializes_to("56h", "56H", DurationUnit::Hours, 56); | ||
assert_deserializes_to("7d", "7D", DurationUnit::Days, 7); | ||
} | ||
|
||
#[test] | ||
#[should_panic] | ||
pub fn cant_parse_nagative_duration() { | ||
_ = "-12s".parse::<PrettyDuration>().unwrap(); | ||
} | ||
} |