arbiter-worker-0.1.0.0
arbiter-worker
Safe HaskellNone
LanguageGHC2024

Arbiter.Worker.Cron

Description

Cron schedule declarations and worker integration.

Synopsis

Documentation

Source #cronJob :: Text -> Text -> OverlapPolicy -> (TickKind -> UTCTime -> JobWrite payload) -> Either String (CronJob payload)

Arguments

:: Text

Schedule name (used in dedup keys and logging)

-> Text

Cron expression (5-field: minute hour day-of-month month day-of-week)

-> OverlapPolicy 
-> (TickKind -> UTCTime -> JobWrite payload)

Job builder. Receives the tick kind and the tick time.

-> Either String (CronJob payload) 

Build a CronJob. A bad expression returns Left. The expression is evaluated in UTC. cronJobInTimezone is the local-time form. Set backfill by record update.

cronJob "nightly-report" "0 3 * * *" SkipOverlap
  (\_kind _tick -> defaultJob (GenerateReport "nightly"))

Source #cronJobInTimezone :: Text -> Text -> Text -> OverlapPolicy -> (TickKind -> UTCTime -> JobWrite payload) -> Either String (CronJob payload)

Arguments

:: Text

Schedule name

-> Text

IANA tz name (e.g. "America/New_York")

-> Text

Cron expression (5-field)

-> OverlapPolicy 
-> (TickKind -> UTCTime -> JobWrite payload) 
-> Either String (CronJob payload) 

Like cronJob but evaluated in a specific timezone. The tz name is validated eagerly against the bundled tzdata database.

Source #enumMinutes :: UTCTime -> UTCTime -> [UTCTime]

Enumerate all minute-boundary times from start through end (inclusive). Both start and end should be truncated to minute boundaries.

Source #formatMinute :: UTCTime -> Text

Format a UTCTime as YYYY-MM-DDTHH:MM for dedup key buckets.

Source #formatMinuteInTimezone :: Maybe Text -> UTCTime -> Text

Format a UTC tick as YYYY-MM-DDTHH:MM in the given timezone. DST fall-back maps two UTC instants to the same local minute. Dedup keys built from it collapse those to a single fire.

Source #matchesInTimezone :: Maybe Text -> CronSchedule -> UTCTime -> Bool

Match a cron schedule against a UTC tick, evaluated in tz. Nothing means UTC. An unknown tz name returns False.

Source #nextRunFromExpression :: Maybe Text -> Text -> UTCTime -> Maybe UTCTime

'nextRunInTimezone' over an unparsed expression. A bad one returns 'Nothing'.

Source #nextRunInTimezone :: Maybe Text -> CronSchedule -> UTCTime -> Maybe UTCTime

The first tick after now that sched matches, evaluated in tz. Nothing means UTC. An unknown tz name returns Nothing.

A replayed local minute is reported. Its insert is deduped while the earlier run is still live.

Source #overlapPolicyToText :: OverlapPolicy -> Text

Convert an OverlapPolicy to its text representation.

Source #resolveTZ :: Text -> Maybe TZ

Look up an IANA tz name in the bundled tzdata database.

Source #truncateToMinute :: UTCTime -> UTCTime

Truncate a UTCTime to the current minute (zero out seconds).

Source #validateCronScheduleUpdate :: CronScheduleUpdate -> Either Text ()

Check a cron patch before it is written. At tick time a bad override stops firing or falls back to the default.

Source #data BackfillPolicy

Bound on replay of missed ticks. Applies at startup and mid-flight.

Constructors

NoBackfill

Drop missed minutes silently. Default.

Backfill NominalDiffTime

Replay missed minutes up to the given duration.

Instances

Instances details
Eq BackfillPolicy Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

Generic BackfillPolicy Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

Associated Types

type Rep BackfillPolicy 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep BackfillPolicy = D1 ('MetaData "BackfillPolicy" "Arbiter.Worker.Cron.Types" "arbiter-worker-0.1.0.0-inplace" 'False) (C1 ('MetaCons "NoBackfill" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Backfill" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 NominalDiffTime)))
Show BackfillPolicy Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep BackfillPolicy Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep BackfillPolicy = D1 ('MetaData "BackfillPolicy" "Arbiter.Worker.Cron.Types" "arbiter-worker-0.1.0.0-inplace" 'False) (C1 ('MetaCons "NoBackfill" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Backfill" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 NominalDiffTime)))

Source #data CronJob payload

A cron schedule. Built with cronJob, or cronJobInTimezone for a non-UTC one.

Constructors

CronJob 

Fields

Instances

Instances details
Generic (CronJob payload) Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

Associated Types

type Rep (CronJob payload) 
Instance details

Defined in Arbiter.Worker.Cron.Types

Methods

#from :: CronJob payload -> Rep (CronJob payload) x

#to :: Rep (CronJob payload) x -> CronJob payload

type Rep (CronJob payload) Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

Source #data OverlapPolicy

How overlapping cron ticks are deduplicated.

Constructors

SkipOverlap

At most one pending or running job per schedule.

AllowOverlap

One job per tick. Concurrent execution of prior ticks is allowed.

Instances

Instances details
Eq OverlapPolicy Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

Generic OverlapPolicy Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

Associated Types

type Rep OverlapPolicy 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep OverlapPolicy = D1 ('MetaData "OverlapPolicy" "Arbiter.Worker.Cron.Types" "arbiter-worker-0.1.0.0-inplace" 'False) (C1 ('MetaCons "SkipOverlap" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "AllowOverlap" 'PrefixI 'False) (U1 :: Type -> Type))
Show OverlapPolicy Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep OverlapPolicy Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep OverlapPolicy = D1 ('MetaData "OverlapPolicy" "Arbiter.Worker.Cron.Types" "arbiter-worker-0.1.0.0-inplace" 'False) (C1 ('MetaCons "SkipOverlap" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "AllowOverlap" 'PrefixI 'False) (U1 :: Type -> Type))

Source #data TickKind

Whether a tick is for the current minute or a replay of a past minute.

Constructors

Live 
Replay 

Instances

Instances details
Eq TickKind Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

Generic TickKind Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

Associated Types

type Rep TickKind 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep TickKind = D1 ('MetaData "TickKind" "Arbiter.Worker.Cron.Types" "arbiter-worker-0.1.0.0-inplace" 'False) (C1 ('MetaCons "Live" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Replay" 'PrefixI 'False) (U1 :: Type -> Type))
Show TickKind Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep TickKind Source # 
Instance details

Defined in Arbiter.Worker.Cron.Types

type Rep TickKind = D1 ('MetaData "TickKind" "Arbiter.Worker.Cron.Types" "arbiter-worker-0.1.0.0-inplace" 'False) (C1 ('MetaCons "Live" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Replay" 'PrefixI 'False) (U1 :: Type -> Type))

Source #computeDelayMicros :: UTCTime -> Int

Delay in microseconds until the next minute boundary, clamped to [0, maxTickDelayMicros].

Source #enumerateCatchUpTicks :: BackfillPolicy -> Maybe UTCTime -> UTCTime -> [UTCTime]

Minutes to evaluate for a processCronCatchUp call. Returns [] when the watermark is at or past currentTick.

Source #initCronSchedules :: MonadArbiter m => SchemaName -> Text -> [CronJob payload] -> LogConfig -> m ()

Upsert default expression and overlap for each CronJob into the cron_schedules table. Preserves any user overrides and enabled state.

Source #makeDedupKey :: CronJob payload -> UTCTime -> Text

Dedup key for a cron job, from its code-defined overlap and timezone.

Source #newCronLog :: MonadIO m => LogConfig -> m CronLog

A CronLog with no gate tripped, for one scheduler run.

Source #processCronCatchUp :: QueueOperation m payload => CronLog -> Text -> Text -> [CronJob payload] -> UTCTime -> m ()

Arguments

:: QueueOperation m payload 
=> CronLog 
-> Text 
-> Text

Queue name

-> [CronJob payload] 
-> UTCTime

Current wall-clock time

-> m () 

Scheduler catch-up step. Each cron runs in its own transaction. Backfill schedules hold a per-(schema, queue, name) advisory lock.

Source #processRunRequests :: forall payload m. QueueOperation m payload => CronLog -> Text -> [CronJob payload] -> UTCTime -> m ()

Claim and fire every schedule with a pending run request. A SkipOverlap schedule reuses its constant dedup key. A manual run is skipped while one of its jobs is active.

The claim and the insert are atomic. If either fails the other rolls back.

Source #runCronScheduler :: QueueOperation m payload => TVar WorkerState -> TVar Bool -> LogConfig -> SchemaName -> Text -> [CronJob payload] -> m ()

Arguments

:: QueueOperation m payload 
=> TVar WorkerState 
-> TVar Bool

Set by the run-now listener when a schedule this pool owns is requested.

-> LogConfig 
-> SchemaName 
-> Text

Queue name (recorded on each schedule row).

-> [CronJob payload] 
-> m () 

Scheduler entry point. Exits when the worker state becomes ShuttingDown.

Source #data CronLog

The scheduler's logger with the gates its repeating failures report through.