packages feed

montage-0.1: Network/Riak/Montage/Util.hs

module Network.Riak.Montage.Util where

import Control.Monad (forever)
import Control.Exception (try, SomeException)
import Control.Applicative
import Control.Concurrent (threadDelay)

import Data.Aeson (Value, (.=), object)

import Data.Time.Clock (getCurrentTime)
import Data.Time.Format (formatTime)
import System.Locale (defaultTimeLocale)
import System.IO (hPutStrLn, stderr)

import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.ByteString.Char8 as S


type LogCallback = B.ByteString -> Maybe Double -> Value -> IO ()

logError :: String -> IO ()
logError s = do
    time <- formatTime defaultTimeLocale "%Y/%m/%d %H:%M:%S" <$> getCurrentTime
    hPutStrLn stderr $ "[" ++ time ++ "] " ++ s

sTl :: S.ByteString -> B.ByteString
sTl s = B.fromChunks [s]

lTs :: B.ByteString -> S.ByteString
lTs l = S.concat $ B.toChunks l

supervise :: String -> IO () -> IO ()
supervise label a = loggedSupervise noopLog label a
    where
        noopLog _ _ _ = threadDelay 200000

loggedSupervise :: LogCallback -> String -> IO () -> IO ()
loggedSupervise netlog label a = forever $ do
    logStart
    res <- try a
    case res of
        Left (e :: SomeException) -> logException e
        Right _               -> logTerminate -- unexpected!
  where
    logStart = logError ("{supervisor " ++ label ++ "} RESTARTED")
    logException e = do
        logError ("{supervisor " ++ label ++ "} EXCEPTION: "++ (show e))
        netlog "EXCEPTION" Nothing $ object ["label" .= label,
                                             "exception" .= show e]
    logTerminate = logError ("{supervisor " ++ label ++ "} EXITED!?")