<commit_before>module Job where

import Control.Concurrent
import System.Exit
import System.Process
import Text.Regex.Posix

data Job = Job
    { jobId :: String
    , name :: String
    , args :: [String]
    , matchExpr :: String
    , status :: Status
    , thread :: Maybe ThreadId
    }

data Status = Idle | Working | Fail String

fullName :: Job -> String
fullName (Job { name = name, args = args }) = name ++ " " ++ unwords args

isFailed :: Job -> Bool
isFailed (Job { status = Fail _ }) = True
isFailed _ = False

processJob :: String -> String -> [String] -> String -> Job
processJob jobId name args expr = Job jobId name args expr Idle Nothing

runAllJobs :: (String -> Status -> IO ()) -> [Job] -> IO [Job]
runAllJobs signalResult = mapM (reRunJob signalResult)

reRunJobs :: FilePath -> (String -> Status -> IO ()) -> [Job] -> IO [Job]
reRunJobs fileChanged signalResult = mapM reRunIfMatch
    where
        reRunIfMatch job =
            if fileChanged =~ matchExpr job
                then reRunJob signalResult job
                else return job

reRunJob :: (String -> Status -> IO ()) -> Job -> IO Job
reRunJob signalResult job = do
    cancel job
    -- NOTE: signalResult must be called asynchronoulsy, otherwise the lock for
    -- jobsRef will deadlock.
    threadId <- forkIO $ runThread job signalResult
    return $ job { thread = Just threadId, status = Working }

cancel :: Job -> IO ()
cancel Job { thread = Just id } = killThread id
cancel _ = return ()

runThread :: Job -> (String -> Status -> IO ()) -> IO ()
runThread job signalResult = do
    -- NOTE: Is the process killed if this thread is killed? If not, is that
    -- the reason why we get resource exhaustion sometimes?
    (exit, stdout, stderr) <- readProcessWithExitCode (name job) (args job) ""
    if exit == ExitSuccess<commit_msg>Align text.<commit_after>module Job where

import Control.Concurrent
import System.Exit
import System.Process
import Text.Regex.Posix

data Job = Job
    { jobId     :: String
    , name      :: String
    , args      :: [String]
    , matchExpr :: String
    , status    :: Status
    , thread    :: Maybe ThreadId
    }

data Status = Idle | Working | Fail String

fullName :: Job -> String
fullName (Job { name = name, args = args }) = name ++ " " ++ unwords args

isFailed :: Job -> Bool
isFailed (Job { status = Fail _ }) = True
isFailed _                         = False

processJob :: String -> String -> [String] -> String -> Job
processJob jobId name args expr = Job jobId name args expr Idle Nothing

runAllJobs :: (String -> Status -> IO ()) -> [Job] -> IO [Job]
runAllJobs signalResult = mapM (reRunJob signalResult)

reRunJobs :: FilePath -> (String -> Status -> IO ()) -> [Job] -> IO [Job]
reRunJobs fileChanged signalResult = mapM reRunIfMatch
    where
        reRunIfMatch job =
            if fileChanged =~ matchExpr job
                then reRunJob signalResult job
                else return job

reRunJob :: (String -> Status -> IO ()) -> Job -> IO Job
reRunJob signalResult job = do
    cancel job
    -- NOTE: signalResult must be called asynchronoulsy, otherwise the lock for
    -- jobsRef will deadlock.
    threadId <- forkIO $ runThread job signalResult
    return $ job { thread = Just threadId, status = Working }

cancel :: Job -> IO ()
cancel Job { thread = Just id } = killThread id
cancel _                        = return ()

runThread :: Job -> (String -> Status -> IO ()) -> IO ()
runThread job signalResult = do
    -- NOTE: Is the process killed if this thread is killed? If not, is that
    -- the reason why we get resource exhaustion sometimes?
    (exit, stdout, stderr) <- readProcessWithExitCode (name job) (args job) ""
    if exit == ExitSuccess
{'fraction_non_alphanumeric': 0.10926174496644295, 'fraction_numerical': 0.0, 'mean_word_length': 2.6601178781925343, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2579520', 'n_tokens_mistral': 1059, 'n_tokens_neox': 1044, 'n_words': 410}