@hackage yesod-worker0.0.1

Drop-in(ish) background worker system for Yesod apps

See the demo for an example site with workers set up.

Usage

Define your Job type

-- Up to you where this goes, so long as it's importable
data AppJob = CountJob Int | UserJob

Include a queue in your foundation data type

-- Foundation.hs
import Yesod.Worker (JobQueue, YesodWorker(..), defaultRunW)

data App = App
  { settings :: AppConfig DefaultEnv Extra
  ...
  , appQueue :: JobQueue AppJob
  }

Specify how to run your jobs

-- Foundation.hs (provided you don't want to orphan the instance)
instance YesodWorker App where
  type Job = AppJob
  queue = appQueue
  runW = defaultRunW persistConfig connPool

  -- Dummy implementations, obviously these would depend on your app
  perform (CountJob n) = void . forM [1..n] $ \k -> do
    lift . putStrLn . show $ k
    lift $ threadDelay 1000000
  perform UserJob = do
    -- Note that you can run SQL using the `runW` helper
    n <- runW $ count ([] :: [Filter User])
    lift . putStrLn $ "There are " ++ (show n) ++ " users"

Start the queue on app boot

-- Application.hs
import Yesod.Worker (emptyQueue, spawnWorkers)

makeFoundation conf = do
  ...
  q <- emptyQueue
  let foundation = App conf ... q
  spawnWorkers foundation
  ...

Queue up a job

import Yesod.Worker (enqueue)

getWhateverR = do
  enqueue $ CountJob 10
  ...

TODO

  • Simplify installation?
  • Include job subsite for viewing queue and worker status
  • Swappable queue backends (for e.g. Redis)
  • Improve error handling / job failures / worker restarts
  • Allow multiple queues with customizable priority