packages feed

angel-0.2.1: Angel/Config.hs

module Angel.Config where

import qualified Data.Map as M
import Control.Concurrent.STM
import Control.Concurrent.STM.TVar (readTVar, writeTVar)
import Text.ParserCombinators.Parsec.Error (ParseError)

import Angel.Parse (parseConfig)
import Angel.Job (syncSupervisors)
import Angel.Data
import Angel.Log (logger)
import Angel.Util (waitForWake)

-- |produce a mapping of name -> program for every program
buildConfigMap :: Spec -> SpecKey
buildConfigMap cfg = M.fromList [(name p, p) | p <- cfg]

-- |invoke the parser to process the file at configPath
-- |produce a SpecKey
processConfig :: String -> IO (Either String SpecKey)
processConfig configPath = do 
    mc <- catch ( do
            c <- readFile configPath 
            return $ Just c
            ) (\e-> return Nothing)

    res <- case mc of 
        Just c -> do
            let cfg = parseConfig c
            case cfg of
                Left e -> return $ Left $ show e
                Right cfg -> do return $ Right $ buildConfigMap cfg
        Nothing -> return $ Left ("could not read config file at " ++ configPath)
    return res

-- |given a new SpecKey just parsed from the file, update the 
-- |shared state TVar
updateSpecConfig :: TVar GroupConfig -> SpecKey -> STM ()
updateSpecConfig sharedGroupConfig spec = do 
    cfg <- readTVar sharedGroupConfig
    writeTVar sharedGroupConfig cfg{spec=spec}

-- |read the config file, update shared state with current spec, 
-- |re-sync running supervisors, wait for the HUP TVar, then repeat!
monitorConfig :: String -> TVar GroupConfig -> TVar (Maybe Int) -> IO ()
monitorConfig configPath sharedGroupConfig wakeSig = do 
    let log = logger "config-monitor"
    mspec <- processConfig configPath
    case mspec of 
        Left e     -> do 
            log $ " <<<< Config Error >>>>\n" ++ e
            log " <<<< Config Error: Skipping reload >>>>"
        Right spec -> do 
            atomically $ updateSpecConfig sharedGroupConfig spec
            syncSupervisors sharedGroupConfig
    waitForWake wakeSig
    log "HUP caught, reloading config"