CronNotAfter

This commit is contained in:
Gregor Kleen 2018-10-24 16:13:13 +02:00
parent b288b56e1d
commit c50b24b962
3 changed files with 64 additions and 29 deletions

View File

@ -165,37 +165,66 @@ nextCronMatch :: TZ -- ^ Timezone of the `Cron`-Entry
-> UTCTime -- ^ Current time, used only for `CronCalendar` -> UTCTime -- ^ Current time, used only for `CronCalendar`
-> Cron -> Cron
-> CronNextMatch UTCTime -> CronNextMatch UTCTime
nextCronMatch tz mPrev now c@Cron{..} nextCronMatch tz mPrev now c@Cron{..} = case notAfter of
| isNothing mPrev MatchAsap -> MatchNone
= execRef now False cronInitial MatchAt ts
| Just prevT <- mPrev | MatchAt ts' <- nextMatch
= case cronRepeat of , ts' <= ts -> MatchAt ts'
CronRepeatOnChange | MatchAsap <- nextMatch
| not $ matchesCron tz Nothing prevT c , now <= ts -> MatchAsap
-> let | otherwise -> MatchNone
cutoffTime = addUTCTime cronRateLimit prevT MatchNone -> nextMatch
in case execRef now False cronInitial of
MatchAsap
| now < cutoffTime -> MatchAt cutoffTime
MatchAt ts
| ts < cutoffTime -> MatchAt cutoffTime
other -> other
CronRepeatScheduled cronNext
-> case cronNext of
CronAsap
| addUTCTime cronRateLimit prevT <= now
-> MatchAsap
| otherwise
-> MatchAt $ addUTCTime cronRateLimit prevT
cronNext
-> execRef (addUTCTime cronRateLimit prevT) True cronNext
_other -> MatchNone
where where
execRef ref wasExecd cronAbsolute = case cronAbsolute of nextMatch = nextCronMatch' tz mPrev now c
CronAsap -> MatchAsap notAfter
| Right c' <- cronNotAfter
, Just ref <- notAfterRef
= execRef' ref False c'
| Left diff <- cronNotAfter
, Just ref <- notAfterRef
= MatchAt $ diff `addUTCTime` ref
| otherwise = MatchNone
notAfterRef
| Just prevT <- mPrev = Just prevT
| otherwise = case execRef' now False cronInitial of
MatchAt t -> Just t
MatchNone -> Nothing
nextCronMatch' tz mPrev now c@Cron{..}
| isNothing mPrev
= execRef now False cronInitial
| Just prevT <- mPrev
= case cronRepeat of
CronRepeatOnChange
| not $ matchesCron tz Nothing prevT c
-> let
cutoffTime = addUTCTime cronRateLimit prevT
in case execRef now False cronInitial of
MatchAsap
| now < cutoffTime -> MatchAt cutoffTime
MatchAt ts
| ts < cutoffTime -> MatchAt cutoffTime
other -> other
CronRepeatScheduled cronNext
-> case cronNext of
CronAsap
| addUTCTime cronRateLimit prevT <= now
-> MatchAsap
| otherwise
-> MatchAt $ addUTCTime cronRateLimit prevT
cronNext
-> execRef (addUTCTime cronRateLimit prevT) True cronNext
_other -> MatchNone
execRef ref wasExecd cronAbsolute = case execRef' ref wasExecd cronAbsolute of
MatchAt t
| t <= ref -> MatchAsap
other -> other
execRef' ref wasExecd cronAbsolute = case cronAbsolute of
CronAsap -> MatchAt ref
CronTimestamp{ cronTimestamp = localTimeToUTCTZ tz -> ts } CronTimestamp{ cronTimestamp = localTimeToUTCTZ tz -> ts }
| ref <= ts -> MatchAt ts | ref <= ts || not wasExecd -> MatchAt ts
| not wasExecd -> MatchAsap
| otherwise -> MatchNone | otherwise -> MatchNone
CronCalendar{..} -> listToMatch $ do CronCalendar{..} -> listToMatch $ do
let CronDate{..} = toCronDate $ utcToLocalTimeTZ tz ref let CronDate{..} = toCronDate $ utcToLocalTimeTZ tz ref
@ -213,6 +242,7 @@ nextCronMatch tz mPrev now c@Cron{..}
localDay <- maybeToList $ fromGregorianValid (fromIntegral cronYear) (fromIntegral cronMonth) (fromIntegral cronDayOfMonth) localDay <- maybeToList $ fromGregorianValid (fromIntegral cronYear) (fromIntegral cronMonth) (fromIntegral cronDayOfMonth)
let localTimeOfDay = TimeOfDay (fromIntegral cronHour) (fromIntegral cronMinute) (fromIntegral cronSecond) let localTimeOfDay = TimeOfDay (fromIntegral cronHour) (fromIntegral cronMinute) (fromIntegral cronSecond)
return $ localTimeToUTCTZ tz LocalTime{..} return $ localTimeToUTCTZ tz LocalTime{..}
CronNotScheduled -> MatchNone
matchesCron :: TZ -- ^ Timezone of the `Cron`-Entry matchesCron :: TZ -- ^ Timezone of the `Cron`-Entry
-> Maybe UTCTime -- ^ Previous execution of the job -> Maybe UTCTime -- ^ Previous execution of the job

View File

@ -57,6 +57,7 @@ data Cron = Cron
{ cronInitial :: CronAbsolute { cronInitial :: CronAbsolute
, cronRepeat :: CronRepeat , cronRepeat :: CronRepeat
, cronRateLimit :: NominalDiffTime , cronRateLimit :: NominalDiffTime
, cronNotAfter :: Either NominalDiffTime CronAbsolute
} }
deriving (Eq, Show) deriving (Eq, Show)

View File

@ -33,6 +33,7 @@ determineCrontab = execWriterT $ do
{ cronInitial = CronAsap { cronInitial = CronAsap
, cronRepeat = CronRepeatScheduled CronAsap , cronRepeat = CronRepeatScheduled CronAsap
, cronRateLimit = interval , cronRateLimit = interval
, cronNotAfter = Right CronNotScheduled
} }
Nothing -> return () Nothing -> return ()
@ -42,6 +43,7 @@ determineCrontab = execWriterT $ do
{ cronInitial = CronAsap { cronInitial = CronAsap
, cronRepeat = CronRepeatScheduled CronAsap , cronRepeat = CronRepeatScheduled CronAsap
, cronRateLimit = appJobCronInterval , cronRateLimit = appJobCronInterval
, cronNotAfter = Right CronNotScheduled
} }
let let
@ -52,6 +54,7 @@ determineCrontab = execWriterT $ do
{ cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ sheetActiveFrom { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ sheetActiveFrom
, cronRepeat = CronRepeatOnChange -- Allow repetition of the notification (if something changes), but wait at least an hour , cronRepeat = CronRepeatOnChange -- Allow repetition of the notification (if something changes), but wait at least an hour
, cronRateLimit = appNotificationRateLimit , cronRateLimit = appNotificationRateLimit
, cronNotAfter = Right . CronTimestamp $ utcToLocalTimeTZ appTZ sheetActiveTo
} }
tell $ HashMap.singleton tell $ HashMap.singleton
(JobCtlQueue $ JobQueueNotification NotificationSheetInactive{..}) (JobCtlQueue $ JobQueueNotification NotificationSheetInactive{..})
@ -59,5 +62,6 @@ determineCrontab = execWriterT $ do
{ cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ . max sheetActiveFrom $ addUTCTime (-nominalDay) sheetActiveTo { cronInitial = CronTimestamp . utcToLocalTimeTZ appTZ . max sheetActiveFrom $ addUTCTime (-nominalDay) sheetActiveTo
, cronRepeat = CronRepeatOnChange , cronRepeat = CronRepeatOnChange
, cronRateLimit = appNotificationRateLimit , cronRateLimit = appNotificationRateLimit
, cronNotAfter = Right . CronTimestamp $ utcToLocalTimeTZ appTZ sheetActiveTo
} }
runConduit $ transPipe lift (selectSource [] []) .| C.mapM_ sheetJobs runConduit $ transPipe lift (selectSource [] []) .| C.mapM_ sheetJobs