1 {-# LANGUAGE MultiWayIf, FunctionalDependencies, MultiParamTypeClasses #-}
2 module Gargantext.Utils.Jobs.Monad where
4 import Gargantext.Utils.Jobs.Settings
5 import Gargantext.Utils.Jobs.Map
6 import Gargantext.Utils.Jobs.Queue
7 import Gargantext.Utils.Jobs.State
9 import Control.Concurrent.STM
10 import Control.Exception
11 import Control.Monad.Except
13 import Data.Time.Clock
14 import Network.HTTP.Client (Manager)
17 import qualified Servant.Job.Core as SJ
18 import qualified Servant.Job.Types as SJ
20 data JobEnv t w a = JobEnv
21 { jeSettings :: JobSettings
22 , jeState :: JobsState t w a
23 , jeManager :: Manager
27 :: (EnumBounded t, Monoid w)
32 newJobEnv js prios mgr = JobEnv js <$> newJobsState js prios <*> pure mgr
34 defaultJobSettings :: SJ.SecretKey -> JobSettings
35 defaultJobSettings k = JobSettings
37 , jsJobTimeout = 30 * 60 -- 30 minutes
38 , jsIDTimeout = 30 * 60 -- 30 minutes
39 , jsGcPeriod = 1 * 60 -- 1 minute
43 genSecret :: IO SJ.SecretKey
44 genSecret = SJ.generateSecretKey
46 class MonadIO m => MonadJob m t w a | m -> t w a where
47 getJobEnv :: m (JobEnv t w a)
49 getJobsSettings :: MonadJob m t w a => m JobSettings
50 getJobsSettings = jeSettings <$> getJobEnv
52 getJobsState :: MonadJob m t w a => m (JobsState t w a)
53 getJobsState = jeState <$> getJobEnv
55 getJobsMap :: MonadJob m t w a => m (JobMap (SJ.JobID 'SJ.Safe) w a)
56 getJobsMap = jobsData <$> getJobsState
58 getJobsQueue :: MonadJob m t w a => m (Queue t (SJ.JobID 'SJ.Safe))
59 getJobsQueue = jobsQ <$> getJobsState
62 :: (MonadJob m t w a, Ord t)
65 -> (i -> Logger w -> IO a)
66 -> m (SJ.JobID 'SJ.Safe)
67 queueJob jobkind input f = do
70 liftIO (pushJob jobkind input f js st)
75 -> m (Maybe (JobEntry (SJ.JobID 'SJ.Safe) w a))
78 liftIO $ lookupJob jid jmap
85 | JobException SomeException
90 => SJ.JobID 'SJ.Unsafe
91 -> m (Either JobError (SJ.JobID 'SJ.Safe))
92 checkJID (SJ.PrivateID tn n t d) = do
93 now <- liftIO getCurrentTime
95 if | tn /= "job" -> return (Left InvalidIDType)
96 | now > addUTCTime (fromIntegral $ jsIDTimeout js) t -> return (Left IDExpired)
97 | d /= SJ.macID tn (jsSecretKey js) t n -> return (Left InvalidMacID)
98 | otherwise -> return $ Right (SJ.PrivateID tn n t d)
102 => SJ.JobID 'SJ.Unsafe
103 -> (SJ.JobID 'SJ.Safe -> JobEntry (SJ.JobID 'SJ.Safe) w a -> m r)
104 -> m (Either JobError (Maybe r))
108 Left e -> return (Left e)
112 Nothing -> return (Right Nothing)
113 Just j -> Right . Just <$> f jid' j
118 -> m (Either JobError a)
120 handleIDError toE act = act >>= \r -> case r of
121 Left err -> throwError (toE err)
125 :: (Ord t, MonadJob m t w a)
126 => Bool -- is it queued (and we have to remove jid from queue)
130 removeJob queued t jid = do
133 liftIO . atomically $ do