faktory 1.1.2.7 → 1.1.3.0
raw patch · 5 files changed
+218/−2 lines, 5 filesdep +microlensdep +resource-pooldep +unliftioPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: microlens, resource-pool, unliftio
API changes (from Hackage documentation)
+ Data.Pool.Compat: createPool :: IO a -> (a -> IO ()) -> Double -> Int -> IO (Pool a)
+ Data.Pool.Compat: data () => LocalPool a
+ Data.Pool.Compat: data () => Pool a
+ Data.Pool.Compat: data () => PoolConfig a
+ Data.Pool.Compat: defaultPoolConfig :: IO a -> (a -> IO ()) -> Double -> Int -> PoolConfig a
+ Data.Pool.Compat: destroyAllResources :: Pool a -> IO ()
+ Data.Pool.Compat: destroyResource :: Pool a -> LocalPool a -> a -> IO ()
+ Data.Pool.Compat: newPool :: PoolConfig a -> IO (Pool a)
+ Data.Pool.Compat: putResource :: LocalPool a -> a -> IO ()
+ Data.Pool.Compat: setNumStripes :: Maybe Int -> PoolConfig a -> PoolConfig a
+ Data.Pool.Compat: takeResource :: Pool a -> IO (a, LocalPool a)
+ Data.Pool.Compat: tryTakeResource :: Pool a -> IO (Maybe (a, LocalPool a))
+ Data.Pool.Compat: tryWithResource :: Pool a -> (a -> IO r) -> IO (Maybe r)
+ Data.Pool.Compat: withResource :: Pool a -> (a -> IO r) -> IO r
+ Faktory.Pool: at :: UTCTime -> JobOptions
+ Faktory.Pool: buildJob :: (MonadUnliftIO m, MonadReader env m, HasFaktoryPool env) => JobOptions -> arg -> m (Job arg)
+ Faktory.Pool: class HasFaktoryPool env
+ Faktory.Pool: custom :: ToJSON a => a -> JobOptions
+ Faktory.Pool: data FaktoryPool
+ Faktory.Pool: data Job arg
+ Faktory.Pool: data JobOptions
+ Faktory.Pool: data PoolSettings
+ Faktory.Pool: data Settings
+ Faktory.Pool: faktoryPoolL :: HasFaktoryPool env => Lens' env FaktoryPool
+ Faktory.Pool: in_ :: NominalDiffTime -> JobOptions
+ Faktory.Pool: instance Faktory.Pool.HasFaktoryPool Faktory.Pool.FaktoryPool
+ Faktory.Pool: jobArg :: Job arg -> arg
+ Faktory.Pool: jobReserveForMicroseconds :: Job arg -> Int
+ Faktory.Pool: jobRetriesRemaining :: Job arg -> Int
+ Faktory.Pool: jobtype :: String -> JobOptions
+ Faktory.Pool: newFaktoryPool :: MonadIO m => Settings -> PoolSettings -> m FaktoryPool
+ Faktory.Pool: newJob :: arg -> IO (Job arg)
+ Faktory.Pool: once :: JobOptions
+ Faktory.Pool: perform :: (MonadUnliftIO m, MonadReader env m, HasFaktoryPool env, ToJSON arg, HasCallStack) => JobOptions -> arg -> m JobId
+ Faktory.Pool: queue :: Queue -> JobOptions
+ Faktory.Pool: reserveFor :: Natural -> JobOptions
+ Faktory.Pool: retry :: Int -> JobOptions
+ Faktory.Pool: takeProducer :: (MonadIO m, MonadReader env m, HasFaktoryPool env) => m (Producer, m ())
+ Faktory.Pool: type JobId = String
+ Faktory.Pool: withProducer :: (MonadUnliftIO m, MonadReader env m, HasFaktoryPool env) => (Producer -> m a) -> m a
+ Faktory.Settings: PoolSettings :: Natural -> Natural -> PoolSettings
+ Faktory.Settings: [settingsSize] :: PoolSettings -> Natural
+ Faktory.Settings: [settingsTimeout] :: PoolSettings -> Natural
+ Faktory.Settings: data PoolSettings
+ Faktory.Settings: envPoolSettings :: IO PoolSettings
+ Network.Connection.Compat: [settingClientSupported] :: TLSSettings -> Supported
- Network.Connection.Compat: TLSSettingsSimple :: Bool -> Bool -> Bool -> TLSSettings
+ Network.Connection.Compat: TLSSettingsSimple :: Bool -> Bool -> Bool -> Supported -> TLSSettings
Files
- CHANGELOG.md +8/−1
- faktory.cabal +6/−1
- library/Data/Pool/Compat.hs +31/−0
- library/Faktory/Pool.hs +126/−0
- library/Faktory/Settings.hs +47/−0
CHANGELOG.md view
@@ -1,4 +1,11 @@-## [_Unreleased_](https://github.com/frontrowed/faktory_worker_haskell/compare/v1.1.2.7...main)+## [_Unreleased_](https://github.com/frontrowed/faktory_worker_haskell/compare/v1.1.3.0...main)++## [v1.1.3.0](https://github.com/frontrowed/faktory_worker_haskell/compare/v1.1.2.7...v1.1.3.0)++- Add `Faktory.Pool`++ This incurs the new dependencies, `unliftio`, `resource-pool`, and+ `microlens`. ## [v1.1.2.7](https://github.com/frontrowed/faktory_worker_haskell/compare/v1.1.2.6...v1.1.2.7)
faktory.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.18 name: faktory-version: 1.1.2.7+version: 1.1.3.0 license: MIT license-file: LICENSE copyright: 2018 Freckle Education@@ -51,6 +51,7 @@ library exposed-modules:+ Data.Pool.Compat Faktory.Client Faktory.Connection Faktory.Ent.Batch@@ -61,6 +62,7 @@ Faktory.JobFailure Faktory.JobOptions Faktory.JobState+ Faktory.Pool Faktory.Prelude Faktory.Producer Faktory.Protocol@@ -97,15 +99,18 @@ errors >=2.3.0, megaparsec >=8.0.0, memory >=0.15.0,+ microlens >=0.4.11.2, mtl >=2.2.2, network >=3.1.1.1, random >=1.1,+ resource-pool >=0.2.3.2, safe-exceptions >=0.1.7.1, scanner >=0.3.1, semigroups >=0.19.1, text >=1.2.4.0, time >=1.9.3, unix >=2.7.2.2,+ unliftio >=0.2.13.1, unordered-containers >=0.2.10.0 if impl(ghc >=8.10)
+ library/Data/Pool/Compat.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE CPP #-}++module Data.Pool.Compat+ ( module Data.Pool+ , createPool+ ) where++import Prelude++import Data.Pool hiding (createPool)+#if MIN_VERSION_resource_pool(0,3,0)+#else+import Control.Concurrent (getNumCapabilities)+import qualified Data.Pool as Pool+#endif++createPool+ :: IO a+ -> (a -> IO ())+ -> Double+ -> Int+ -> IO (Pool a)+createPool create destroy timeout size = do+#if MIN_VERSION_resource_pool(0,3,0)+ newPool $ defaultPoolConfig create destroy timeout size+#else+ -- Re-implement instead of using the deprecated compatibility function, so+ -- that we can get a consistent numStripes and size behavior.+ numStripes <- getNumCapabilities+ Pool.createPool create destroy numStripes (realToFrac timeout) size+#endif
+ library/Faktory/Pool.hs view
@@ -0,0 +1,126 @@+module Faktory.Pool+ ( FaktoryPool+ , HasFaktoryPool (..)++ -- * Pool Construction+ , Settings+ , PoolSettings+ , newFaktoryPool++ -- * Pool use+ , perform+ , buildJob++ -- * Direct access+ , withProducer+ , takeProducer++ -- * Re-exports+ , module Faktory.Job+ ) where++import Faktory.Prelude++import Control.Monad.IO.Class (MonadIO (..))+import Control.Monad.Reader (MonadReader, asks)+import Data.Aeson (ToJSON)+import Data.Pool.Compat (Pool)+import qualified Data.Pool.Compat as Pool+import Faktory.Job hiding (buildJob, perform)+import qualified Faktory.Job as Job+import Faktory.Producer+import Faktory.Settings (PoolSettings (..), Settings)+import GHC.Stack (HasCallStack)+import Lens.Micro (Lens', (^.))+import UnliftIO (MonadUnliftIO, withRunInIO)++-- |+--+-- @since 1.1.3.0+newtype FaktoryPool = FaktoryPool (Pool Producer)++-- |+--+-- @since 1.1.3.0+class HasFaktoryPool env where+ faktoryPoolL :: Lens' env FaktoryPool++instance HasFaktoryPool FaktoryPool where+ faktoryPoolL = id++-- | Build a 'FaktoryPool' with the given settings+--+-- See 'Settings', 'envSettings', 'PoolSettings', and 'envPoolSettings'.+--+-- @since 1.1.3.0+newFaktoryPool+ :: MonadIO m+ => Settings+ -> PoolSettings+ -> m FaktoryPool+newFaktoryPool settings PoolSettings {..} = do+ liftIO $+ FaktoryPool+ <$> Pool.createPool+ (newProducer settings)+ closeProducer+ (fromIntegral settingsTimeout)+ (fromIntegral settingsSize)++-- | 'Faktory.Job.perform' but using a 'Producer' from the pool+--+-- @since 1.1.3.0+perform+ :: ( MonadUnliftIO m+ , MonadReader env m+ , HasFaktoryPool env+ , ToJSON arg+ , HasCallStack+ )+ => JobOptions+ -> arg+ -> m JobId+perform options arg = do+ withProducer $ \producer -> do+ liftIO $ Job.perform options producer arg++-- | 'Faktory.Job.buildJob' but using a 'Producer' from the pool+--+-- @since 1.1.3.0+buildJob+ :: (MonadUnliftIO m, MonadReader env m, HasFaktoryPool env)+ => JobOptions+ -> arg+ -> m (Job arg)+buildJob options arg = do+ withProducer $ \producer -> do+ liftIO $ Job.buildJob options producer arg++-- | Acquire a 'Producer', use it, and return it to the pool+--+-- @since 1.1.3.0+withProducer+ :: (MonadUnliftIO m, MonadReader env m, HasFaktoryPool env)+ => (Producer -> m a)+ -> m a+withProducer f = do+ FaktoryPool p <- asks (^. faktoryPoolL)+ withRunInIO $ \runInIO -> do+ Pool.withResource p $ runInIO . f++-- | Get a 'Producer' from the pool along with an action to return it+--+-- You should prefer 'withProducer' if at all possible. With this function you+-- are responsible to ensure the return action is called (e.g. with 'finally').+--+-- This is only necessary if you are operating in a monad that doesn't have+-- 'MonadUnliftIO' (like 'ConduitT'), so you need to take and return a+-- 'Producer' separately (e.g. with 'bracketP').+--+-- @since 1.1.3.0+takeProducer+ :: (MonadIO m, MonadReader env m, HasFaktoryPool env) => m (Producer, m ())+takeProducer = do+ FaktoryPool p <- asks (^. faktoryPoolL)+ (producer, lp) <- liftIO $ Pool.takeResource p+ pure (producer, liftIO $ Pool.putResource lp producer)
library/Faktory/Settings.hs view
@@ -2,6 +2,8 @@ ( Settings (..) , defaultSettings , envSettings++ -- * Worker , WorkerSettings (..) , defaultWorkerSettings , envWorkerSettings@@ -12,6 +14,10 @@ , WorkerId , randomWorkerId + -- * Pool+ , PoolSettings (..)+ , envPoolSettings+ -- * Re-exports , ConnectionInfo (..) , Namespace (..)@@ -23,6 +29,7 @@ import Faktory.Connection import Faktory.JobOptions (JobOptions) import Faktory.Settings.Queue+import Numeric.Natural import System.Environment (lookupEnv) import System.IO (hPutStrLn, stderr) import System.Random@@ -82,3 +89,43 @@ randomWorkerId :: IO WorkerId randomWorkerId = WorkerId . take 8 . randomRs ('a', 'z') <$> newStdGen++-- |+--+-- @since 1.1.3.0+data PoolSettings = PoolSettings+ { settingsSize :: Natural+ -- ^ Maximum pool size+ --+ -- Default is @10@. Smallest acceptable value is @1@. Note that, due to the+ -- striping behavior of @resource-pool@, a configured size @N@ may result in+ -- @N - 1@ resources.+ , settingsTimeout :: Natural+ -- ^ How long before destroying a resource, in seconds+ --+ -- Default is @600@.+ }++-- |+--+-- @since 1.1.3.0+defaultPoolSettings :: PoolSettings+defaultPoolSettings =+ PoolSettings+ { settingsSize = 10+ , settingsTimeout = 600+ }++-- | Read 'PoolSettings' from the environment+--+-- - @FAKTORY_POOL_SIZE@+-- - @FAKTORY_POOL_TIMEOUT@+--+-- @since 1.1.3.0+envPoolSettings :: IO PoolSettings+envPoolSettings =+ PoolSettings+ <$> (maybe settingsSize read <$> lookupEnv "FAKTORY_POOL_SIZE")+ <*> (maybe settingsTimeout read <$> lookupEnv "FAKTORY_POOL_TIMEOUT")+ where+ PoolSettings {..} = defaultPoolSettings