Skip to content

Commit

Permalink
add second buck executable that runs the multiplexing server
Browse files Browse the repository at this point in the history
  • Loading branch information
tek committed Nov 20, 2024
1 parent 72cf34e commit 79872af
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 85 deletions.
1 change: 1 addition & 0 deletions buck-worker-2/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export_file("Main.hs", visibility = ["PUBLIC"])
165 changes: 165 additions & 0 deletions buck-worker-2/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
{-# language DataKinds, OverloadedLists, OverloadedStrings, GADTs #-}

module Main where

import Internal.Log (dbg)
import Args (BuckArgs (..), CompileResult (..), parseBuckArgs, toGhcArgs, writeResult)
import BuckWorker (
ExecuteCommand (..),
ExecuteCommand_EnvironmentEntry (..),
ExecuteEvent (..),
ExecuteResponse (..),
Worker (..),
workerServer,
)
import Control.Concurrent.MVar (MVar)
import Control.Concurrent.STM (TVar, newTVarIO)
import Control.Exception (SomeException (SomeException), throwIO, try)
import Control.Monad (when)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Except (ExceptT, runExceptT, throwE)
import Control.Monad.Trans.Reader (runReaderT)
import Data.Foldable (traverse_)
import Data.Map (Map)
import qualified Data.Map.Strict as Map
import Data.Maybe (maybeToList)
import Data.String (fromString)
import qualified Data.Text as Text
import Data.Text.Encoding (decodeUtf8Lenient)
import qualified Data.Text.Lazy as LazyText
import qualified Data.Vector as Vector
import GHC (getSession)
import Internal.AbiHash (readAbiHash)
import Internal.Args (Args (..))
import Internal.Cache (Cache (..), emptyCache)
import Internal.Log (newLog)
import Internal.Session (Env (..), withGhc)
import Message
import Network.GRPC.HighLevel.Generated (
GRPCMethodType (..),
ServerRequest (..),
ServerResponse (..),
ServiceOptions (..),
StatusCode (..),
defaultServiceOptions,
)
import Pool (Pool (..), dumpStatus, removeWorker)
import Prelude hiding (log)
import Server (assignLoop)
import System.Environment (lookupEnv)
import System.IO (BufferMode (LineBuffering), hPutStrLn, hSetBuffering, stderr, stdout)
import Worker (work)

commandEnv :: Vector.Vector ExecuteCommand_EnvironmentEntry -> Map String String
commandEnv =
Map.fromList .
fmap (\ (ExecuteCommand_EnvironmentEntry key value) -> (fromBs key, fromBs value)) .
Vector.toList
where
fromBs = Text.unpack . decodeUtf8Lenient

abiHashIfSuccess :: Env -> BuckArgs -> Int -> IO (Maybe CompileResult)
abiHashIfSuccess env args code
| 0 == code
= withGhc env \ _ -> do
hsc_env <- getSession
abiHash <- readAbiHash hsc_env args.abiOut
pure (Just CompileResult {abiHash})
| otherwise
= pure Nothing

note :: String -> Maybe a -> ExceptT String IO a
note msg = \case
Just a -> pure a
Nothing -> throwE msg

processRequest :: TVar Pool -> BuckArgs -> Env -> IO (Maybe CompileResult, String)
processRequest pool buckArgs env@Env {args} = do
either (Nothing,) id <$> runExceptT do
ghcPath <- note "no --ghc-path given" args.ghcPath
requestWorkerTargetId <- Just . TargetId <$> note "no --worker-target-id given" args.workerTargetId
liftIO do
(j, i, hset) <- assignLoop ghcPath (maybeToList buckArgs.pluginDb) pool requestWorkerTargetId
let
req = Request {
requestWorkerTargetId,
requestWorkerClose = False,
requestEnv = Map.toList args.env,
requestArgs = "-c" : args.ghcOptions
}
Response {responseResult = code, ..} <- runReaderT (work req) (j, i, hset, pool)
result <- abiHashIfSuccess env buckArgs code
dbg ("Code: " ++ show code)
dbg ("Result: " ++ show result)
when (requestWorkerClose req) do
traverse_ (removeWorker pool) requestWorkerTargetId
dumpStatus pool
pure (result, unlines (responseConsoleStdOut ++ responseConsoleStdErr))

executeHandler ::
MVar Cache ->
TVar Pool ->
ServerRequest 'Normal ExecuteCommand ExecuteResponse ->
IO (ServerResponse 'Normal ExecuteResponse)
executeHandler cache pool (ServerNormalRequest _ ExecuteCommand {executeCommandArgv, executeCommandEnv}) = do
hPutStrLn stderr (unlines argv)
response <- either exceptionResponse successResponse =<< try run
pure (ServerNormalResponse response [] StatusOk "")
where
run = do
buckArgs <- either (throwIO . userError) pure (parseBuckArgs (commandEnv executeCommandEnv) argv)
args <- toGhcArgs buckArgs
log <- newLog False
result <- processRequest pool buckArgs Env {cache, args, log}
pure (buckArgs, result)

successResponse (buckArgs, (result, diagnostics)) = do
executeResponseExitCode <- writeResult buckArgs result
pure ExecuteResponse {
executeResponseExitCode,
executeResponseStderr = LazyText.pack diagnostics
}

exceptionResponse (SomeException e) =
pure ExecuteResponse {
executeResponseExitCode = 1,
executeResponseStderr = "Uncaught exception: " <> LazyText.pack (show e)
}

argv = Text.unpack . decodeUtf8Lenient <$> Vector.toList executeCommandArgv

execHandler ::
ServerRequest 'ClientStreaming ExecuteEvent ExecuteResponse ->
IO (ServerResponse 'ClientStreaming ExecuteResponse)
execHandler (ServerReaderRequest _metadata _recv) = do
hPutStrLn stderr "Received Exec"
error "not implemented"

handlers :: MVar Cache -> TVar Pool -> Worker ServerRequest ServerResponse
handlers cache srv =
Worker
{ workerExecute = executeHandler cache srv,
workerExec = execHandler
}

main :: IO ()
main = do
hSetBuffering stdout LineBuffering
hSetBuffering stderr LineBuffering
socket <- lookupEnv "WORKER_SOCKET"
hPutStrLn stderr $ "using worker socket: " <> show socket
let
n = 1
thePool = Pool
{ poolLimit = n,
poolNewWorkerId = 1,
poolNewJobId = 1,
poolStatus = mempty,
poolHandles = []
}

poolRef <- newTVarIO thePool
cache <- emptyCache False
workerServer (handlers cache poolRef) (maybe id setSocket socket defaultServiceOptions)
where
setSocket s options = options {serverHost = fromString ("unix://" <> s <> "\x00"), serverPort = 0}
14 changes: 13 additions & 1 deletion buck-worker/Args.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import Internal.AbiHash (AbiHash (..))
import qualified Internal.Args
import Internal.Args (Args (Args))

-- | Right now the 'Maybe' just corresponds to the presence of the CLI argument @--abi-out@ – errors occuring while
-- reading the iface are thrown.
data CompileResult =
CompileResult {
abiHash :: Maybe AbiHash
Expand All @@ -27,8 +29,11 @@ data BuckArgs =
buck2PackageDb :: [String],
buck2PackageDbDep :: Maybe String,
workerTargetId :: Maybe String,
pluginDb :: Maybe String,
env :: Map String String,
binPath :: [String],
tempDir :: Maybe String,
ghcPath :: Maybe String,
ghcDirFile :: Maybe String,
ghcDbFile :: Maybe String,
ghcOptions :: [String]
Expand All @@ -44,8 +49,11 @@ emptyBuckArgs env =
buck2PackageDb = [],
buck2PackageDbDep = Nothing,
workerTargetId = Nothing,
pluginDb = Nothing,
env,
binPath = [],
tempDir = env !? "TMPDIR",
ghcPath = Nothing,
ghcDirFile = Nothing,
ghcDbFile = Nothing,
ghcOptions = []
Expand All @@ -61,7 +69,8 @@ options =
withArg "--worker-target-id" \ z a -> z {workerTargetId = Just a},
withArg "--worker-socket" const,
skip "--worker-close",
withArg "--ghc" \ z _ -> z {ghcOptions = []},
withArg "--plugin-db" \ z a -> z {pluginDb = Just a},
withArg "--ghc" \ z a -> z {ghcOptions = [], ghcPath = Just a},
withArg "--ghc-dir" \ z a -> z {ghcDirFile = Just a},
withArg "--extra-pkg-db" \ z a -> z {ghcDbFile = Just a},
withArg "--bin-path" \ z a -> z {binPath = a : z.binPath},
Expand Down Expand Up @@ -95,8 +104,11 @@ toGhcArgs args = do
packageDb <- readPath args.ghcDbFile
pure Args {
topdir,
workerTargetId = args.workerTargetId,
env = args.env,
binPath = args.binPath,
tempDir = args.tempDir,
ghcPath = args.ghcPath,
ghcOptions = args.ghcOptions ++ foldMap packageDbArg packageDb ++ foldMap packageDbArg args.buck2PackageDb
}
where
Expand Down
4 changes: 1 addition & 3 deletions buck-worker/BUCK
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export_file("Args.hs", visibility = ["PUBLIC"])
export_file("Main.hs", visibility = ["PUBLIC"])
export_file("Worker.hs", visibility = ["PUBLIC"])
[export_file(f, visibility = ["PUBLIC"]) for f in ["Args.hs", "Main.hs", "BuckWorker.hs"]]
4 changes: 2 additions & 2 deletions buck-worker/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import BuckWorker (
Worker (..),
workerServer,
)
import Control.Concurrent.MVar (MVar, newMVar, readMVar)
import Control.Concurrent.MVar (MVar)
import Control.Exception (SomeException (SomeException), throwIO, try)
import Data.Map (Map)
import qualified Data.Map.Strict as Map
Expand All @@ -24,7 +24,7 @@ import GHC (Ghc, Phase, getSession)
import Internal.AbiHash (readAbiHash)
import Internal.Cache (Cache (..), emptyCache)
import Internal.Compile (compile)
import Internal.Log (Log (..), newLog)
import Internal.Log (logFlush, newLog)
import Internal.Session (Env (..), withGhc)
import Network.GRPC.HighLevel.Generated (
GRPCMethodType (..),
Expand Down
1 change: 1 addition & 0 deletions comm/src/BUCK
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[export_file(f, visibility = ["PUBLIC"]) for f in ["Message.hs"]]
2 changes: 1 addition & 1 deletion comm/src/Message.hs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ data Request = Request
instance Binary Request

data Response = Response
{ responseResult :: [String],
{ responseResult :: Int,
responseConsoleStdOut :: [String],
responseConsoleStdErr :: [String]
}
Expand Down
7 changes: 7 additions & 0 deletions plugin/ghc-persistent-worker-plugin.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ library
Util
if (impl(ghc > 9.11))
hs-source-dirs: src-ghcHEAD
other-modules: GHC.Main
Logger
build-depends: base ^>=4.21,

if (impl(ghc >= 9.9) && impl(ghc < 9.11))
hs-source-dirs: src-ghc98
other-modules: GHC.Main
Logger
build-depends: base ^>=4.20,
Expand All @@ -48,6 +54,7 @@ library
filepath,
ghc,
ghc-boot,
text,
time,
transformers,
unix
Expand Down
48 changes: 21 additions & 27 deletions plugin/src-ghc98/GHC/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,7 @@ main' postLoadMode units dflags0 args flagWarnings = do
let diag_opts = initDiagOpts dflags4
let flagWarnings' = GhcDriverMessage <$> mconcat [warnsToMessages diag_opts flagWarnings, dynamicFlagWarnings]

handleSourceError (\e -> do
GHC.printException e
liftIO $ exitWith (ExitFailure 1)) $ do
liftIO $ printOrThrowDiagnostics logger4 (initPrintConfig dflags4) diag_opts flagWarnings'
liftIO $ printOrThrowDiagnostics logger4 (initPrintConfig dflags4) diag_opts flagWarnings'

liftIO $ showBanner postLoadMode dflags4

Expand Down Expand Up @@ -296,29 +293,26 @@ main' postLoadMode units dflags0 args flagWarnings = do
liftIO $ checkOptions postLoadMode dflags6 srcs objs units

---------------- Do the business -----------
handleSourceError (\e -> do
GHC.printException e
liftIO $ exitWith (ExitFailure 1)) $ do
case postLoadMode of
ShowInterface f -> liftIO $ showIface logger
(hsc_dflags hsc_env)
(hsc_units hsc_env)
(hsc_NC hsc_env)
f
ShowInterfaceAbiHash f -> liftIO $ showIfaceAbiHash logger
(hsc_dflags hsc_env)
(hsc_NC hsc_env)
f
DoMake -> doMake units srcs
DoMkDependHS -> doMkDependHS (map fst srcs)
StopBefore p -> liftIO (oneShot hsc_env p srcs)
DoInteractive -> ghciUI units srcs Nothing
DoEval exprs -> ghciUI units srcs $ Just $ reverse exprs
DoRun -> doRun units srcs args
DoAbiHash -> abiHash (map fst srcs)
ShowPackages -> liftIO $ showUnits hsc_env
DoFrontend f -> doFrontend f srcs
DoBackpack -> doBackpack (map fst srcs)
case postLoadMode of
ShowInterface f -> liftIO $ showIface logger
(hsc_dflags hsc_env)
(hsc_units hsc_env)
(hsc_NC hsc_env)
f
-- ShowInterfaceAbiHash f -> liftIO $ showIfaceAbiHash logger
-- (hsc_dflags hsc_env)
-- (hsc_NC hsc_env)
-- f
DoMake -> doMake units srcs
DoMkDependHS -> doMkDependHS (map fst srcs)
StopBefore p -> liftIO (oneShot hsc_env p srcs)
DoInteractive -> ghciUI units srcs Nothing
DoEval exprs -> ghciUI units srcs $ Just $ reverse exprs
DoRun -> doRun units srcs args
DoAbiHash -> abiHash (map fst srcs)
ShowPackages -> liftIO $ showUnits hsc_env
DoFrontend f -> doFrontend f srcs
DoBackpack -> doBackpack (map fst srcs)

liftIO $ dumpFinalStats logger

Expand Down
16 changes: 9 additions & 7 deletions plugin/src/BUCK
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export_file("Internal/AbiHash.hs", visibility = ["PUBLIC"])
export_file("Internal/Args.hs", visibility = ["PUBLIC"])
export_file("Internal/Cache.hs", visibility = ["PUBLIC"])
export_file("Internal/Compile.hs", visibility = ["PUBLIC"])
export_file("Internal/Error.hs", visibility = ["PUBLIC"])
export_file("Internal/Log.hs", visibility = ["PUBLIC"])
export_file("Internal/Session.hs", visibility = ["PUBLIC"])
[export_file("Internal/" + f + ".hs", visibility = ["PUBLIC"]) for f in [
"AbiHash",
"Args",
"Cache",
"Compile",
"Error",
"Log",
"Session",
]]
Loading

0 comments on commit 79872af

Please sign in to comment.