{-# LANGUAGE NoFieldSelectors #-}
{-# OPTIONS_HADDOCK not-home #-}

-- | Internal to the arbiter packages. Not covered by the PVP.
--
-- The job record type and its field accessors.
module Arbiter.Core.Job.Types.Internal
  ( JobRecord (..)
  , Job
  , Stored (..)
  , storedBytes
  , primaryKey
  , payload
  , queueName
  , groupKey
  , insertedAt
  , updatedAt
  , attempts
  , lastError
  , priority
  , lastAttemptedAt
  , notVisibleUntil
  , dedupKey
  , maxAttempts
  , parentId
  , parentState
  , traceContext
  , suspended
  , claimedBy
  , claimSeq
  , archiveFor
  , payloadKeys
  ) where

import Data.Aeson (FromJSON (..), ToJSON (..), Value (Null), decodeStrict, encode)
import Data.Aeson.Encoding (unsafeToEncoding)
import Data.ByteString (ByteString)
import Data.ByteString.Builder (byteString)
import Data.ByteString.Lazy qualified as BL
import Data.Int (Int32, Int64)
import Data.Kind (Type)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Data.Time (UTCTime)
import Data.UUID.Types (UUID)

import Arbiter.Core.Job.Dedup (DedupKey)
import Arbiter.Core.Job.TraceContext (TraceContext)

-- | A payload as the JSON bytes the database holds. The type it decodes to is a phantom.
newtype Stored (payload :: Type) = Stored ByteString
  deriving stock (Stored payload -> Stored payload -> Bool
(Stored payload -> Stored payload -> Bool)
-> (Stored payload -> Stored payload -> Bool)
-> Eq (Stored payload)
forall payload. Stored payload -> Stored payload -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall payload. Stored payload -> Stored payload -> Bool
== :: Stored payload -> Stored payload -> Bool
$c/= :: forall payload. Stored payload -> Stored payload -> Bool
/= :: Stored payload -> Stored payload -> Bool
Eq, Int -> Stored payload -> ShowS
[Stored payload] -> ShowS
Stored payload -> String
(Int -> Stored payload -> ShowS)
-> (Stored payload -> String)
-> ([Stored payload] -> ShowS)
-> Show (Stored payload)
forall payload. Int -> Stored payload -> ShowS
forall payload. [Stored payload] -> ShowS
forall payload. Stored payload -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall payload. Int -> Stored payload -> ShowS
showsPrec :: Int -> Stored payload -> ShowS
$cshow :: forall payload. Stored payload -> String
show :: Stored payload -> String
$cshowList :: forall payload. [Stored payload] -> ShowS
showList :: [Stored payload] -> ShowS
Show)

-- | The JSON bytes of a stored payload.
storedBytes :: Stored payload -> ByteString
storedBytes :: forall payload. Stored payload -> ByteString
storedBytes (Stored ByteString
bytes) = ByteString
bytes

-- | The bytes are emitted as they are. 'toJSON' has to parse them back.
instance ToJSON (Stored payload) where
  toJSON :: Stored payload -> Value
toJSON = Value -> Maybe Value -> Value
forall a. a -> Maybe a -> a
fromMaybe Value
Null (Maybe Value -> Value)
-> (Stored payload -> Maybe Value) -> Stored payload -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Maybe Value
forall a. FromJSON a => ByteString -> Maybe a
decodeStrict (ByteString -> Maybe Value)
-> (Stored payload -> ByteString) -> Stored payload -> Maybe Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stored payload -> ByteString
forall payload. Stored payload -> ByteString
storedBytes
  toEncoding :: Stored payload -> Encoding
toEncoding = Builder -> Encoding
forall a. Builder -> Encoding' a
unsafeToEncoding (Builder -> Encoding)
-> (Stored payload -> Builder) -> Stored payload -> Encoding
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
byteString (ByteString -> Builder)
-> (Stored payload -> ByteString) -> Stored payload -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stored payload -> ByteString
forall payload. Stored payload -> ByteString
storedBytes

instance FromJSON (Stored payload) where
  parseJSON :: Value -> Parser (Stored payload)
parseJSON = Stored payload -> Parser (Stored payload)
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Stored payload -> Parser (Stored payload))
-> (Value -> Stored payload) -> Value -> Parser (Stored payload)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Stored payload
forall payload. ByteString -> Stored payload
Stored (ByteString -> Stored payload)
-> (Value -> ByteString) -> Value -> Stored payload
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LazyByteString -> ByteString
BL.toStrict (LazyByteString -> ByteString)
-> (Value -> LazyByteString) -> Value -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> LazyByteString
forall a. ToJSON a => a -> LazyByteString
encode

-- | Internal representation shared by writable and stored jobs.
data JobRecord payload key q insertedAt adm = Job
  { forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> key
primaryKey :: key
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> payload
payload :: payload
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> q
queueName :: q
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Text
groupKey :: Maybe Text
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> insertedAt
insertedAt :: insertedAt
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UTCTime
updatedAt :: Maybe UTCTime
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Int32
attempts :: Int32
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Text
lastError :: Maybe Text
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Int32
priority :: Int32
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UTCTime
lastAttemptedAt :: Maybe UTCTime
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UTCTime
notVisibleUntil :: Maybe UTCTime
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe DedupKey
dedupKey :: Maybe DedupKey
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Int32
maxAttempts :: Maybe Int32
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Int64
parentId :: Maybe Int64
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Value
parentState :: Maybe Value
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe TraceContext
traceContext :: Maybe TraceContext
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Bool
suspended :: Bool
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UUID
claimedBy :: Maybe UUID
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Int64
claimSeq :: Int64
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Int32
archiveFor :: Maybe Int32
  , forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> adm
payloadKeys :: adm
  }
  deriving stock (JobRecord payload key q insertedAt adm
-> JobRecord payload key q insertedAt adm -> Bool
(JobRecord payload key q insertedAt adm
 -> JobRecord payload key q insertedAt adm -> Bool)
-> (JobRecord payload key q insertedAt adm
    -> JobRecord payload key q insertedAt adm -> Bool)
-> Eq (JobRecord payload key q insertedAt adm)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall payload key q insertedAt adm.
(Eq key, Eq payload, Eq q, Eq insertedAt, Eq adm) =>
JobRecord payload key q insertedAt adm
-> JobRecord payload key q insertedAt adm -> Bool
$c== :: forall payload key q insertedAt adm.
(Eq key, Eq payload, Eq q, Eq insertedAt, Eq adm) =>
JobRecord payload key q insertedAt adm
-> JobRecord payload key q insertedAt adm -> Bool
== :: JobRecord payload key q insertedAt adm
-> JobRecord payload key q insertedAt adm -> Bool
$c/= :: forall payload key q insertedAt adm.
(Eq key, Eq payload, Eq q, Eq insertedAt, Eq adm) =>
JobRecord payload key q insertedAt adm
-> JobRecord payload key q insertedAt adm -> Bool
/= :: JobRecord payload key q insertedAt adm
-> JobRecord payload key q insertedAt adm -> Bool
Eq, Int -> JobRecord payload key q insertedAt adm -> ShowS
[JobRecord payload key q insertedAt adm] -> ShowS
JobRecord payload key q insertedAt adm -> String
(Int -> JobRecord payload key q insertedAt adm -> ShowS)
-> (JobRecord payload key q insertedAt adm -> String)
-> ([JobRecord payload key q insertedAt adm] -> ShowS)
-> Show (JobRecord payload key q insertedAt adm)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall payload key q insertedAt adm.
(Show key, Show payload, Show q, Show insertedAt, Show adm) =>
Int -> JobRecord payload key q insertedAt adm -> ShowS
forall payload key q insertedAt adm.
(Show key, Show payload, Show q, Show insertedAt, Show adm) =>
[JobRecord payload key q insertedAt adm] -> ShowS
forall payload key q insertedAt adm.
(Show key, Show payload, Show q, Show insertedAt, Show adm) =>
JobRecord payload key q insertedAt adm -> String
$cshowsPrec :: forall payload key q insertedAt adm.
(Show key, Show payload, Show q, Show insertedAt, Show adm) =>
Int -> JobRecord payload key q insertedAt adm -> ShowS
showsPrec :: Int -> JobRecord payload key q insertedAt adm -> ShowS
$cshow :: forall payload key q insertedAt adm.
(Show key, Show payload, Show q, Show insertedAt, Show adm) =>
JobRecord payload key q insertedAt adm -> String
show :: JobRecord payload key q insertedAt adm -> String
$cshowList :: forall payload key q insertedAt adm.
(Show key, Show payload, Show q, Show insertedAt, Show adm) =>
[JobRecord payload key q insertedAt adm] -> ShowS
showList :: [JobRecord payload key q insertedAt adm] -> ShowS
Show)

-- | A job parametrized over payload, primary key, queue name, insertion
-- timestamp, and the columns derived from the payload. The constructor is internal.
type Job payload key q insertedAt adm =
  JobRecord payload key q insertedAt adm

-- | Database-assigned identifier for a stored job.
primaryKey :: Job payload key q insertedAt adm -> key
primaryKey :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> key
primaryKey Job {primaryKey :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> key
primaryKey = key
value} = key
value

-- | User-defined payload stored as JSONB.
payload :: Job payload key q insertedAt adm -> payload
payload :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> payload
payload Job {payload :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> payload
payload = payload
value} = payload
value

-- | Queue containing a stored job.
queueName :: Job payload key q insertedAt adm -> q
queueName :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> q
queueName Job {queueName :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> q
queueName = q
value} = q
value

-- | Serial-processing group, or 'Nothing' for an ungrouped job.
groupKey :: Job payload key q insertedAt adm -> Maybe Text
groupKey :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Text
groupKey Job {groupKey :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Text
groupKey = Maybe Text
value} = Maybe Text
value

-- | Time at which the job was inserted.
insertedAt :: Job payload key q insertedAt adm -> insertedAt
insertedAt :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> insertedAt
insertedAt Job {insertedAt :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> insertedAt
insertedAt = insertedAt
value} = insertedAt
value

-- | Time at which the job was last updated.
updatedAt :: Job payload Int64 q insertedAt adm -> Maybe UTCTime
updatedAt :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Maybe UTCTime
updatedAt Job {updatedAt :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UTCTime
updatedAt = Maybe UTCTime
value} = Maybe UTCTime
value

-- | Number of attempts made so far.
attempts :: Job payload Int64 q insertedAt adm -> Int32
attempts :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Int32
attempts Job {attempts :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Int32
attempts = Int32
value} = Int32
value

-- | Error message from the last failed attempt.
lastError :: Job payload Int64 q insertedAt adm -> Maybe Text
lastError :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Maybe Text
lastError Job {lastError :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Text
lastError = Maybe Text
value} = Maybe Text
value

-- | Claim priority. Lower numbers have higher priority. In a group, a retried job goes first.
priority :: Job payload key q insertedAt adm -> Int32
priority :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Int32
priority Job {priority :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Int32
priority = Int32
value} = Int32
value

-- | Time at which a worker last claimed the job.
lastAttemptedAt :: Job payload Int64 q insertedAt adm -> Maybe UTCTime
lastAttemptedAt :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Maybe UTCTime
lastAttemptedAt Job {lastAttemptedAt :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UTCTime
lastAttemptedAt = Maybe UTCTime
value} = Maybe UTCTime
value

-- | Earliest time at which the job can be claimed.
notVisibleUntil :: Job payload key q insertedAt adm -> Maybe UTCTime
notVisibleUntil :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UTCTime
notVisibleUntil Job {notVisibleUntil :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UTCTime
notVisibleUntil = Maybe UTCTime
value} = Maybe UTCTime
value

-- | Deduplication strategy and key.
dedupKey :: Job payload key q insertedAt adm -> Maybe DedupKey
dedupKey :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe DedupKey
dedupKey Job {dedupKey :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe DedupKey
dedupKey = Maybe DedupKey
value} = Maybe DedupKey
value

-- | Attempt limit before the job moves to the DLQ.
maxAttempts :: Job payload key q insertedAt adm -> Maybe Int32
maxAttempts :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Int32
maxAttempts Job {maxAttempts :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Int32
maxAttempts = Maybe Int32
value} = Maybe Int32
value

-- | Identifier of this job's parent in a job tree.
parentId :: Job payload Int64 q insertedAt adm -> Maybe Int64
parentId :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Maybe Int64
parentId Job {parentId :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Int64
parentId = Maybe Int64
value} = Maybe Int64
value

-- | Snapshot of accumulated child results for a rollup finalizer.
parentState :: Job payload Int64 q insertedAt adm -> Maybe Value
parentState :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Maybe Value
parentState Job {parentState :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Value
parentState = Maybe Value
value} = Maybe Value
value

-- | W3C trace context captured at enqueue.
traceContext :: Job payload key q insertedAt adm -> Maybe TraceContext
traceContext :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe TraceContext
traceContext Job {traceContext :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe TraceContext
traceContext = Maybe TraceContext
value} = Maybe TraceContext
value

-- | Whether the job is suspended. It stays unclaimable until resumed.
suspended :: Job payload Int64 q insertedAt adm -> Bool
suspended :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Bool
suspended Job {suspended :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Bool
suspended = Bool
value} = Bool
value

-- | Holder of the outstanding claim. 'Nothing' when no claim is outstanding.
claimedBy :: Job payload Int64 q insertedAt adm -> Maybe UUID
claimedBy :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Maybe UUID
claimedBy Job {claimedBy :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe UUID
claimedBy = Maybe UUID
value} = Maybe UUID
value

-- | The claim token.
claimSeq :: Job payload Int64 q insertedAt adm -> Int64
claimSeq :: forall payload q insertedAt adm.
Job payload Int64 q insertedAt adm -> Int64
claimSeq Job {claimSeq :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Int64
claimSeq = Int64
value} = Int64
value

-- | Completed-job archive retention in seconds.
archiveFor :: Job payload key q insertedAt adm -> Maybe Int32
archiveFor :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Int32
archiveFor Job {archiveFor :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> Maybe Int32
archiveFor = Maybe Int32
value} = Maybe Int32
value

-- | The labels and keys stamped from the payload at enqueue.
payloadKeys :: Job payload key q insertedAt adm -> adm
payloadKeys :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> adm
payloadKeys Job {payloadKeys :: forall payload key q insertedAt adm.
JobRecord payload key q insertedAt adm -> adm
payloadKeys = adm
value} = adm
value