forked from filipg/gonito
refactor running stuff
This commit is contained in:
parent
f1502c16e4
commit
edf0624b95
@ -5,6 +5,7 @@ import Yesod.Form.Bootstrap3 (BootstrapFormLayout (..), renderBootstrap3,
|
|||||||
withSmallInput)
|
withSmallInput)
|
||||||
|
|
||||||
import Handler.Shared
|
import Handler.Shared
|
||||||
|
import Handler.Runner
|
||||||
import Handler.Extract
|
import Handler.Extract
|
||||||
|
|
||||||
import GEval.Core
|
import GEval.Core
|
||||||
|
@ -8,6 +8,8 @@ import PersistSHA1
|
|||||||
|
|
||||||
import Data.Text as T
|
import Data.Text as T
|
||||||
|
|
||||||
|
import Handler.Runner
|
||||||
|
|
||||||
getMakePublicR :: SubmissionId -> Handler TypedContent
|
getMakePublicR :: SubmissionId -> Handler TypedContent
|
||||||
getMakePublicR submissionId = runViewProgress $ doMakePublic submissionId
|
getMakePublicR submissionId = runViewProgress $ doMakePublic submissionId
|
||||||
|
|
||||||
|
73
Handler/Runner.hs
Normal file
73
Handler/Runner.hs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
module Handler.Runner where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
import System.Process
|
||||||
|
import System.Exit
|
||||||
|
import Control.Concurrent.STM
|
||||||
|
import Control.Concurrent.Lifted (threadDelay)
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
|
||||||
|
type Channel = TChan (Maybe Text)
|
||||||
|
|
||||||
|
runProgram :: Maybe FilePath -> FilePath -> [String] -> Channel -> Handler (ExitCode, Text)
|
||||||
|
runProgram workingDir programPath args chan = do
|
||||||
|
(_, Just hout, Just herr, pid) <-
|
||||||
|
liftIO $ createProcess (proc programPath args){ std_out = CreatePipe,
|
||||||
|
std_err = CreatePipe,
|
||||||
|
cwd = workingDir}
|
||||||
|
(code, out) <- gatherOutput pid hout herr chan
|
||||||
|
_ <- liftIO $ waitForProcess pid
|
||||||
|
return (code, out)
|
||||||
|
|
||||||
|
gatherOutput :: ProcessHandle -> Handle -> Handle -> Channel -> Handler (ExitCode, Text)
|
||||||
|
gatherOutput ph hout herr chan = work mempty mempty
|
||||||
|
where
|
||||||
|
work accout accerr = do
|
||||||
|
-- Read any outstanding input.
|
||||||
|
resterr <- takeABit herr accerr
|
||||||
|
restout <- takeABit hout accout
|
||||||
|
liftIO $ threadDelay 1000000
|
||||||
|
-- Check on the process.
|
||||||
|
s <- liftIO $ getProcessExitCode ph
|
||||||
|
-- Exit or loop.
|
||||||
|
case s of
|
||||||
|
Nothing -> work restout resterr
|
||||||
|
Just ec -> do
|
||||||
|
-- Get any last bit written between the read and the status
|
||||||
|
-- check.
|
||||||
|
_ <- takeFinalBit herr resterr
|
||||||
|
all <- takeFinalBit hout restout
|
||||||
|
return (ec, all)
|
||||||
|
takeABit h acc = do
|
||||||
|
bs <- liftIO $ BS.hGetNonBlocking hout (64 * 1024)
|
||||||
|
let acc' = acc <> (decodeUtf8 bs)
|
||||||
|
let (fullLines, rest) = processOutput acc'
|
||||||
|
mapM_ (msg chan) fullLines
|
||||||
|
return rest
|
||||||
|
takeFinalBit h rest = do
|
||||||
|
last <- liftIO $ BS.hGetContents h
|
||||||
|
let all = rest <> (decodeUtf8 last)
|
||||||
|
mapM_ (msg chan) $ lines all
|
||||||
|
return all
|
||||||
|
|
||||||
|
msg :: Channel -> Text -> Handler ()
|
||||||
|
msg chan m = liftIO $ atom $ writeTChan chan $ Just (m ++ "\n")
|
||||||
|
|
||||||
|
err :: Channel -> Text -> Handler ()
|
||||||
|
err = msg
|
||||||
|
|
||||||
|
raw :: Channel -> Text -> Handler ()
|
||||||
|
raw = msg
|
||||||
|
|
||||||
|
atom = Control.Concurrent.STM.atomically
|
||||||
|
|
||||||
|
processOutput :: Text -> ([Text], Text)
|
||||||
|
processOutput = processOutput' . lines
|
||||||
|
where processOutput' [] = ([], "")
|
||||||
|
processOutput' out = (init out, last out)
|
||||||
|
init [] = []
|
||||||
|
init [x] = []
|
||||||
|
init (x:xs) = (x:(init xs))
|
||||||
|
last [x] = x
|
||||||
|
last (_:xs) = last xs
|
@ -4,10 +4,12 @@ module Handler.Shared where
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Control.Concurrent.STM
|
|
||||||
import Data.IntMap (IntMap)
|
import Data.IntMap (IntMap)
|
||||||
import qualified Data.IntMap as IntMap
|
import qualified Data.IntMap as IntMap
|
||||||
|
|
||||||
|
import Handler.Runner
|
||||||
|
import System.Exit
|
||||||
|
|
||||||
import Network.URI
|
import Network.URI
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
@ -20,8 +22,6 @@ import qualified Crypto.Hash.SHA1 as CHS
|
|||||||
|
|
||||||
import qualified Data.List as DL
|
import qualified Data.List as DL
|
||||||
|
|
||||||
import System.Process
|
|
||||||
import System.Exit
|
|
||||||
import System.Random
|
import System.Random
|
||||||
|
|
||||||
import System.Directory (renameDirectory)
|
import System.Directory (renameDirectory)
|
||||||
@ -38,10 +38,6 @@ import Yesod.Form.Bootstrap3 (bfs)
|
|||||||
import qualified Crypto.Nonce as Nonce
|
import qualified Crypto.Nonce as Nonce
|
||||||
import System.IO.Unsafe (unsafePerformIO)
|
import System.IO.Unsafe (unsafePerformIO)
|
||||||
|
|
||||||
atom = Control.Concurrent.STM.atomically
|
|
||||||
|
|
||||||
type Channel = TChan (Maybe Text)
|
|
||||||
|
|
||||||
arena :: Handler FilePath
|
arena :: Handler FilePath
|
||||||
arena = do
|
arena = do
|
||||||
app <- getYesod
|
app <- getYesod
|
||||||
@ -107,15 +103,6 @@ runViewProgress' route action = do
|
|||||||
writeTVar jobs $ IntMap.delete jobId m
|
writeTVar jobs $ IntMap.delete jobId m
|
||||||
redirect $ route jobId
|
redirect $ route jobId
|
||||||
|
|
||||||
msg :: Channel -> Text -> Handler ()
|
|
||||||
msg chan m = liftIO $ atom $ writeTChan chan $ Just (m ++ "\n")
|
|
||||||
|
|
||||||
err :: Channel -> Text -> Handler ()
|
|
||||||
err = msg
|
|
||||||
|
|
||||||
raw :: Channel -> Text -> Handler ()
|
|
||||||
raw = msg
|
|
||||||
|
|
||||||
validGitProtocols :: [String]
|
validGitProtocols :: [String]
|
||||||
validGitProtocols = ["git", "http", "https", "ssh"]
|
validGitProtocols = ["git", "http", "https", "ssh"]
|
||||||
|
|
||||||
@ -300,58 +287,6 @@ getViewProgressR jobId = do
|
|||||||
loop
|
loop
|
||||||
loop
|
loop
|
||||||
|
|
||||||
runProgram :: Maybe FilePath -> FilePath -> [String] -> Channel -> Handler (ExitCode, Text)
|
|
||||||
runProgram workingDir programPath args chan = do
|
|
||||||
(_, Just hout, Just herr, pid) <-
|
|
||||||
liftIO $ createProcess (proc programPath args){ std_out = CreatePipe,
|
|
||||||
std_err = CreatePipe,
|
|
||||||
cwd = workingDir}
|
|
||||||
(code, out) <- gatherOutput pid hout herr chan
|
|
||||||
_ <- liftIO $ waitForProcess pid
|
|
||||||
return (code, out)
|
|
||||||
|
|
||||||
|
|
||||||
processOutput :: Text -> ([Text], Text)
|
|
||||||
processOutput = processOutput' . lines
|
|
||||||
where processOutput' [] = ([], "")
|
|
||||||
processOutput' out = (init out, last out)
|
|
||||||
init [] = []
|
|
||||||
init [x] = []
|
|
||||||
init (x:xs) = (x:(init xs))
|
|
||||||
last [x] = x
|
|
||||||
last (_:xs) = last xs
|
|
||||||
|
|
||||||
|
|
||||||
gatherOutput :: ProcessHandle -> Handle -> Handle -> Channel -> Handler (ExitCode, Text)
|
|
||||||
gatherOutput ph hout herr chan = work mempty mempty
|
|
||||||
where
|
|
||||||
work accout accerr = do
|
|
||||||
-- Read any outstanding input.
|
|
||||||
resterr <- takeABit herr accerr
|
|
||||||
restout <- takeABit hout accout
|
|
||||||
liftIO $ threadDelay 1000000
|
|
||||||
-- Check on the process.
|
|
||||||
s <- liftIO $ getProcessExitCode ph
|
|
||||||
-- Exit or loop.
|
|
||||||
case s of
|
|
||||||
Nothing -> work restout resterr
|
|
||||||
Just ec -> do
|
|
||||||
-- Get any last bit written between the read and the status
|
|
||||||
-- check.
|
|
||||||
_ <- takeFinalBit herr resterr
|
|
||||||
all <- takeFinalBit hout restout
|
|
||||||
return (ec, all)
|
|
||||||
takeABit h acc = do
|
|
||||||
bs <- liftIO $ BS.hGetNonBlocking hout (64 * 1024)
|
|
||||||
let acc' = acc <> (decodeUtf8 bs)
|
|
||||||
let (fullLines, rest) = processOutput acc'
|
|
||||||
mapM_ (msg chan) fullLines
|
|
||||||
return rest
|
|
||||||
takeFinalBit h rest = do
|
|
||||||
last <- liftIO $ BS.hGetContents h
|
|
||||||
let all = rest <> (decodeUtf8 last)
|
|
||||||
mapM_ (msg chan) $ lines all
|
|
||||||
return all
|
|
||||||
|
|
||||||
randomInt :: Handler Int
|
randomInt :: Handler Int
|
||||||
randomInt = liftIO $ randomIO
|
randomInt = liftIO $ randomIO
|
||||||
|
@ -16,6 +16,7 @@ import qualified Yesod.Table as Table
|
|||||||
|
|
||||||
import Handler.Extract
|
import Handler.Extract
|
||||||
import Handler.Shared
|
import Handler.Shared
|
||||||
|
import Handler.Runner
|
||||||
import Handler.Tables
|
import Handler.Tables
|
||||||
import Handler.TagUtils
|
import Handler.TagUtils
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ library
|
|||||||
Handler.Score
|
Handler.Score
|
||||||
Handler.AchievementUtils
|
Handler.AchievementUtils
|
||||||
Handler.ExtraPoints
|
Handler.ExtraPoints
|
||||||
|
Handler.Runner
|
||||||
|
|
||||||
if flag(dev) || flag(library-only)
|
if flag(dev) || flag(library-only)
|
||||||
cpp-options: -DDEVELOPMENT
|
cpp-options: -DDEVELOPMENT
|
||||||
|
Loading…
Reference in New Issue
Block a user