faktory-1.1.2.0: tests/Faktory/JobSpec.hs
{-# LANGUAGE QuasiQuotes #-}
module Faktory.JobSpec
( spec
) where
import Faktory.Prelude
import Data.Aeson
import Data.Aeson.QQ
import Data.Time (getCurrentTime)
import Faktory.Job
import Faktory.Producer
import Faktory.Settings
import Test.Hspec
spec :: Spec
spec = do
-- https://github.com/contribsys/faktory/issues/374#issuecomment-902075572
describe "jobRetriesRemaining" $ do
it "handles first consumed" $ do
job <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "retry": 2
}
|]
jobRetriesRemaining job `shouldBe` 2
it "handles a first retry" $ do
now <- getCurrentTime
job <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "retry": 2
, "failure":
{ "retry_count": 0
, "failed_at": #{now}
}
}
|]
jobRetriesRemaining job `shouldBe` 1
it "handles a final retry" $ do
now <- getCurrentTime
job <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "retry": 2
, "failure":
{ "retry_count": 1
, "failed_at": #{now}
}
}
|]
jobRetriesRemaining job `shouldBe` 0
it "uses Faktory's default" $ do
job <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
}
|]
jobRetriesRemaining job `shouldBe` 25
it "handles retry -1" $ do
now <- getCurrentTime
job1 <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "retry": -1
}
|]
job2 <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "retry": -1
, "failure":
{ "retry_count": 1
, "failed_at": #{now}
}
}
|]
jobRetriesRemaining job1 `shouldBe` 0
jobRetriesRemaining job2 `shouldBe` 0
it "handles retry 0" $ do
now <- getCurrentTime
job1 <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "retry": 0
}
|]
job2 <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "retry": 0
, "failure":
{ "retry_count": 1
, "failed_at": #{now}
}
}
|]
jobRetriesRemaining job1 `shouldBe` 0
jobRetriesRemaining job2 `shouldBe` 0
it "handles nonsense" $ do
now <- getCurrentTime
job <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "retry": 20
, "failure":
{ "retry_count": 1000
, "failed_at": #{now}
}
}
|]
jobRetriesRemaining job `shouldBe` 0
it "handles reserve_for" $ do
job <- decodeJob [aesonQQ|
{ "jid": "abc"
, "args": [""]
, "reserve_for": 3600
}
|]
jobReserveForMicroseconds job `shouldBe` 3600000000
describe "buildJob" $ do
it "defaults to jobtype 'default'" $ do
bracket (newProducer defaultSettings) closeProducer $ \producer -> do
job <- buildJob @Text mempty producer "text"
jobOptions job `shouldBe` jobtype "Default"
it "adds job option defaults from settings" $ do
let settings = defaultSettings { settingsDefaultJobOptions = retry 5 }
bracket (newProducer settings) closeProducer $ \producer -> do
job <- buildJob @Text mempty producer "text"
jobOptions job `shouldBe` (jobtype "Default" <> retry 5)
it "doesn't prefers explicit job options over defaults in settings" $ do
let settings = defaultSettings { settingsDefaultJobOptions = retry 5 }
bracket (newProducer settings) closeProducer $ \producer -> do
job <- buildJob @Text (retry 88) producer "text"
jobOptions job `shouldBe` (jobtype "Default" <> retry 88)
decodeJob :: Value -> IO (Job Text)
decodeJob v = case fromJSON v of
Error err -> do
expectationFailure $ "Job JSON did not parse: " <> err
error "unreachable" -- I hate that hspec makes ^ IO () and not IO a
Success job -> pure job