module Ecluse.Core.Rules.Freshness (
MaxAdvisoryAge (..),
AdvisoryAgeBasis (..),
maxAdvisoryAgeFor,
AdvisoryPublication (..),
AdvisoryAge (..),
AdvisoryFreshness (..),
assessAdvisoryAge,
ageAlarmStep,
) where
import Data.Time (NominalDiffTime, UTCTime, diffUTCTime)
import Ecluse.Core.Rules.Types (Rule (AllowIfOlderThan))
data MaxAdvisoryAge = MaxAdvisoryAge
{ MaxAdvisoryAge -> NominalDiffTime
maxAdvisoryAge :: NominalDiffTime
, MaxAdvisoryAge -> AdvisoryAgeBasis
maxAdvisoryAgeBasis :: AdvisoryAgeBasis
}
deriving stock (MaxAdvisoryAge -> MaxAdvisoryAge -> Bool
(MaxAdvisoryAge -> MaxAdvisoryAge -> Bool)
-> (MaxAdvisoryAge -> MaxAdvisoryAge -> Bool) -> Eq MaxAdvisoryAge
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MaxAdvisoryAge -> MaxAdvisoryAge -> Bool
== :: MaxAdvisoryAge -> MaxAdvisoryAge -> Bool
$c/= :: MaxAdvisoryAge -> MaxAdvisoryAge -> Bool
/= :: MaxAdvisoryAge -> MaxAdvisoryAge -> Bool
Eq, Int -> MaxAdvisoryAge -> ShowS
[MaxAdvisoryAge] -> ShowS
MaxAdvisoryAge -> String
(Int -> MaxAdvisoryAge -> ShowS)
-> (MaxAdvisoryAge -> String)
-> ([MaxAdvisoryAge] -> ShowS)
-> Show MaxAdvisoryAge
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MaxAdvisoryAge -> ShowS
showsPrec :: Int -> MaxAdvisoryAge -> ShowS
$cshow :: MaxAdvisoryAge -> String
show :: MaxAdvisoryAge -> String
$cshowList :: [MaxAdvisoryAge] -> ShowS
showList :: [MaxAdvisoryAge] -> ShowS
Show)
data AdvisoryAgeBasis
=
AgeConfigured
|
AgeBeforeQuarantine NominalDiffTime
|
AgeFloor
deriving stock (AdvisoryAgeBasis -> AdvisoryAgeBasis -> Bool
(AdvisoryAgeBasis -> AdvisoryAgeBasis -> Bool)
-> (AdvisoryAgeBasis -> AdvisoryAgeBasis -> Bool)
-> Eq AdvisoryAgeBasis
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AdvisoryAgeBasis -> AdvisoryAgeBasis -> Bool
== :: AdvisoryAgeBasis -> AdvisoryAgeBasis -> Bool
$c/= :: AdvisoryAgeBasis -> AdvisoryAgeBasis -> Bool
/= :: AdvisoryAgeBasis -> AdvisoryAgeBasis -> Bool
Eq, Int -> AdvisoryAgeBasis -> ShowS
[AdvisoryAgeBasis] -> ShowS
AdvisoryAgeBasis -> String
(Int -> AdvisoryAgeBasis -> ShowS)
-> (AdvisoryAgeBasis -> String)
-> ([AdvisoryAgeBasis] -> ShowS)
-> Show AdvisoryAgeBasis
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AdvisoryAgeBasis -> ShowS
showsPrec :: Int -> AdvisoryAgeBasis -> ShowS
$cshow :: AdvisoryAgeBasis -> String
show :: AdvisoryAgeBasis -> String
$cshowList :: [AdvisoryAgeBasis] -> ShowS
showList :: [AdvisoryAgeBasis] -> ShowS
Show)
advisoryAgeFloor :: NominalDiffTime
advisoryAgeFloor :: NominalDiffTime
advisoryAgeFloor = NominalDiffTime
259200
advisoryAgeLead :: NominalDiffTime
advisoryAgeLead :: NominalDiffTime
advisoryAgeLead = NominalDiffTime
86400
maxAdvisoryAgeFor :: Maybe NominalDiffTime -> [Rule] -> MaxAdvisoryAge
maxAdvisoryAgeFor :: Maybe NominalDiffTime -> [Rule] -> MaxAdvisoryAge
maxAdvisoryAgeFor (Just NominalDiffTime
explicit) [Rule]
_ = NominalDiffTime -> AdvisoryAgeBasis -> MaxAdvisoryAge
MaxAdvisoryAge NominalDiffTime
explicit AdvisoryAgeBasis
AgeConfigured
maxAdvisoryAgeFor Maybe NominalDiffTime
Nothing [Rule]
rules = MaxAdvisoryAge
-> (NominalDiffTime -> MaxAdvisoryAge)
-> Maybe NominalDiffTime
-> MaxAdvisoryAge
forall b a. b -> (a -> b) -> Maybe a -> b
maybe MaxAdvisoryAge
floorAge NominalDiffTime -> MaxAdvisoryAge
derivedFrom ((Rule -> Maybe NominalDiffTime -> Maybe NominalDiffTime)
-> Maybe NominalDiffTime -> [Rule] -> Maybe NominalDiffTime
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Rule -> Maybe NominalDiffTime -> Maybe NominalDiffTime
earlier Maybe NominalDiffTime
forall a. Maybe a
Nothing [Rule]
rules)
where
earlier :: Rule -> Maybe NominalDiffTime -> Maybe NominalDiffTime
earlier (AllowIfOlderThan NominalDiffTime
quarantine) Maybe NominalDiffTime
soFar = NominalDiffTime -> Maybe NominalDiffTime
forall a. a -> Maybe a
Just (NominalDiffTime
-> (NominalDiffTime -> NominalDiffTime)
-> Maybe NominalDiffTime
-> NominalDiffTime
forall b a. b -> (a -> b) -> Maybe a -> b
maybe NominalDiffTime
quarantine (NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Ord a => a -> a -> a
min NominalDiffTime
quarantine) Maybe NominalDiffTime
soFar)
earlier Rule
_ Maybe NominalDiffTime
soFar = Maybe NominalDiffTime
soFar
derivedFrom :: NominalDiffTime -> MaxAdvisoryAge
derivedFrom NominalDiffTime
quarantine
| NominalDiffTime
quarantine NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
- NominalDiffTime
advisoryAgeLead NominalDiffTime -> NominalDiffTime -> Bool
forall a. Ord a => a -> a -> Bool
> NominalDiffTime
advisoryAgeFloor =
NominalDiffTime -> AdvisoryAgeBasis -> MaxAdvisoryAge
MaxAdvisoryAge (NominalDiffTime
quarantine NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
- NominalDiffTime
advisoryAgeLead) (NominalDiffTime -> AdvisoryAgeBasis
AgeBeforeQuarantine NominalDiffTime
quarantine)
| Bool
otherwise = MaxAdvisoryAge
floorAge
floorAge :: MaxAdvisoryAge
floorAge = NominalDiffTime -> AdvisoryAgeBasis -> MaxAdvisoryAge
MaxAdvisoryAge NominalDiffTime
advisoryAgeFloor AdvisoryAgeBasis
AgeFloor
data AdvisoryAge = AdvisoryAge
{ AdvisoryAge -> UTCTime
advisoryPushedAt :: UTCTime
, AdvisoryAge -> NominalDiffTime
advisoryAge :: NominalDiffTime
, AdvisoryAge -> NominalDiffTime
advisoryMaxAge :: NominalDiffTime
}
deriving stock (AdvisoryAge -> AdvisoryAge -> Bool
(AdvisoryAge -> AdvisoryAge -> Bool)
-> (AdvisoryAge -> AdvisoryAge -> Bool) -> Eq AdvisoryAge
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AdvisoryAge -> AdvisoryAge -> Bool
== :: AdvisoryAge -> AdvisoryAge -> Bool
$c/= :: AdvisoryAge -> AdvisoryAge -> Bool
/= :: AdvisoryAge -> AdvisoryAge -> Bool
Eq, Int -> AdvisoryAge -> ShowS
[AdvisoryAge] -> ShowS
AdvisoryAge -> String
(Int -> AdvisoryAge -> ShowS)
-> (AdvisoryAge -> String)
-> ([AdvisoryAge] -> ShowS)
-> Show AdvisoryAge
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AdvisoryAge -> ShowS
showsPrec :: Int -> AdvisoryAge -> ShowS
$cshow :: AdvisoryAge -> String
show :: AdvisoryAge -> String
$cshowList :: [AdvisoryAge] -> ShowS
showList :: [AdvisoryAge] -> ShowS
Show)
data AdvisoryPublication
=
NoGeneration
|
PublishedAt UTCTime
|
UndatedGeneration
deriving stock (AdvisoryPublication -> AdvisoryPublication -> Bool
(AdvisoryPublication -> AdvisoryPublication -> Bool)
-> (AdvisoryPublication -> AdvisoryPublication -> Bool)
-> Eq AdvisoryPublication
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AdvisoryPublication -> AdvisoryPublication -> Bool
== :: AdvisoryPublication -> AdvisoryPublication -> Bool
$c/= :: AdvisoryPublication -> AdvisoryPublication -> Bool
/= :: AdvisoryPublication -> AdvisoryPublication -> Bool
Eq, Int -> AdvisoryPublication -> ShowS
[AdvisoryPublication] -> ShowS
AdvisoryPublication -> String
(Int -> AdvisoryPublication -> ShowS)
-> (AdvisoryPublication -> String)
-> ([AdvisoryPublication] -> ShowS)
-> Show AdvisoryPublication
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AdvisoryPublication -> ShowS
showsPrec :: Int -> AdvisoryPublication -> ShowS
$cshow :: AdvisoryPublication -> String
show :: AdvisoryPublication -> String
$cshowList :: [AdvisoryPublication] -> ShowS
showList :: [AdvisoryPublication] -> ShowS
Show)
data AdvisoryFreshness
=
AdvisoryFresh
|
AdvisoryAging AdvisoryAge
|
AdvisoryStale AdvisoryAge
|
AdvisoryUndated
deriving stock (AdvisoryFreshness -> AdvisoryFreshness -> Bool
(AdvisoryFreshness -> AdvisoryFreshness -> Bool)
-> (AdvisoryFreshness -> AdvisoryFreshness -> Bool)
-> Eq AdvisoryFreshness
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AdvisoryFreshness -> AdvisoryFreshness -> Bool
== :: AdvisoryFreshness -> AdvisoryFreshness -> Bool
$c/= :: AdvisoryFreshness -> AdvisoryFreshness -> Bool
/= :: AdvisoryFreshness -> AdvisoryFreshness -> Bool
Eq, Int -> AdvisoryFreshness -> ShowS
[AdvisoryFreshness] -> ShowS
AdvisoryFreshness -> String
(Int -> AdvisoryFreshness -> ShowS)
-> (AdvisoryFreshness -> String)
-> ([AdvisoryFreshness] -> ShowS)
-> Show AdvisoryFreshness
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AdvisoryFreshness -> ShowS
showsPrec :: Int -> AdvisoryFreshness -> ShowS
$cshow :: AdvisoryFreshness -> String
show :: AdvisoryFreshness -> String
$cshowList :: [AdvisoryFreshness] -> ShowS
showList :: [AdvisoryFreshness] -> ShowS
Show)
assessAdvisoryAge :: MaxAdvisoryAge -> UTCTime -> AdvisoryPublication -> AdvisoryFreshness
assessAdvisoryAge :: MaxAdvisoryAge
-> UTCTime -> AdvisoryPublication -> AdvisoryFreshness
assessAdvisoryAge MaxAdvisoryAge
limit UTCTime
now = \case
AdvisoryPublication
NoGeneration -> AdvisoryFreshness
AdvisoryFresh
AdvisoryPublication
UndatedGeneration -> AdvisoryFreshness
AdvisoryUndated
PublishedAt UTCTime
pushedAt -> UTCTime -> AdvisoryFreshness
reading UTCTime
pushedAt
where
reading :: UTCTime -> AdvisoryFreshness
reading UTCTime
pushedAt
| NominalDiffTime
age NominalDiffTime -> NominalDiffTime -> Bool
forall a. Ord a => a -> a -> Bool
> NominalDiffTime
maxAge = AdvisoryAge -> AdvisoryFreshness
AdvisoryStale AdvisoryAge
observed
| NominalDiffTime
age NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
+ NominalDiffTime
age NominalDiffTime -> NominalDiffTime -> Bool
forall a. Ord a => a -> a -> Bool
> NominalDiffTime
maxAge = AdvisoryAge -> AdvisoryFreshness
AdvisoryAging AdvisoryAge
observed
| Bool
otherwise = AdvisoryFreshness
AdvisoryFresh
where
age :: NominalDiffTime
age = UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime UTCTime
now UTCTime
pushedAt
maxAge :: NominalDiffTime
maxAge = MaxAdvisoryAge -> NominalDiffTime
maxAdvisoryAge MaxAdvisoryAge
limit
observed :: AdvisoryAge
observed = AdvisoryAge{advisoryPushedAt :: UTCTime
advisoryPushedAt = UTCTime
pushedAt, advisoryAge :: NominalDiffTime
advisoryAge = NominalDiffTime
age, advisoryMaxAge :: NominalDiffTime
advisoryMaxAge = NominalDiffTime
maxAge}
ageAlarmStep :: Bool -> AdvisoryFreshness -> (Bool, Maybe AdvisoryAge)
ageAlarmStep :: Bool -> AdvisoryFreshness -> (Bool, Maybe AdvisoryAge)
ageAlarmStep Bool
latched = \case
AdvisoryFreshness
AdvisoryFresh -> (Bool
False, Maybe AdvisoryAge
forall a. Maybe a
Nothing)
AdvisoryFreshness
AdvisoryUndated -> (Bool
False, Maybe AdvisoryAge
forall a. Maybe a
Nothing)
AdvisoryAging AdvisoryAge
observed -> AdvisoryAge -> (Bool, Maybe AdvisoryAge)
forall {f :: * -> *} {a}. Alternative f => a -> (Bool, f a)
crossing AdvisoryAge
observed
AdvisoryStale AdvisoryAge
observed -> AdvisoryAge -> (Bool, Maybe AdvisoryAge)
forall {f :: * -> *} {a}. Alternative f => a -> (Bool, f a)
crossing AdvisoryAge
observed
where
crossing :: a -> (Bool, f a)
crossing a
observed = (Bool
True, a
observed a -> f () -> f a
forall a b. a -> f b -> f a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Bool -> f ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Bool
not Bool
latched))