{-# LANGUAGE TemplateHaskell, TypeFamilies, EmptyDataDecls #-}
{-# LANGUAGE DeriveGeneric, DeriveLift, NumDecimals #-}
module NgxExport.Tools (
terminateWorkerProcess
,restartWorkerProcess
,finalizeHTTPRequest
,workerProcessIsExiting
,ngxRequestPtr
,ngxNow
,ngxPid
,TimeInterval (..)
,toSec
,threadDelaySec
,readFromByteString
,readFromByteStringAsJSON
,readFromByteStringWithRPtr
,readFromByteStringWithRPtrAsJSON
,ServiceMode (..)
,ngxExportSimpleService
,ngxExportSimpleServiceTyped
,ngxExportSimpleServiceTypedAsJSON
,splitService
,ignitionService
,deferredService
,Foreign.C.Types.CInt (..)
,Foreign.C.Types.CUInt (..)
) where
import NgxExport
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Foreign.Ptr
import Foreign.Storable
import Foreign.C.Types
import qualified Data.ByteString as B
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as C8
import qualified Data.ByteString.Lazy as L
import Data.Binary.Get
import Data.IORef
import Data.Maybe
import Data.Aeson
import Data.Function (on)
import Data.Ord (comparing)
import Control.Monad
import Control.Arrow
import Control.Exception
import Control.Concurrent
import GHC.Generics
import System.IO.Unsafe (unsafePerformIO)
import System.Posix.Types
import Safe
terminateWorkerProcess :: String -> IO ()
terminateWorkerProcess :: String -> IO ()
terminateWorkerProcess = TerminateWorkerProcess -> IO ()
forall e a. Exception e => e -> IO a
throwIO (TerminateWorkerProcess -> IO ())
-> (String -> TerminateWorkerProcess) -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> TerminateWorkerProcess
TerminateWorkerProcess
restartWorkerProcess :: String -> IO ()
restartWorkerProcess :: String -> IO ()
restartWorkerProcess = RestartWorkerProcess -> IO ()
forall e a. Exception e => e -> IO a
throwIO (RestartWorkerProcess -> IO ())
-> (String -> RestartWorkerProcess) -> String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> RestartWorkerProcess
RestartWorkerProcess
finalizeHTTPRequest :: Int -> Maybe String -> IO ()
finalizeHTTPRequest :: Int -> Maybe String -> IO ()
finalizeHTTPRequest = (FinalizeHTTPRequest -> IO ()
forall e a. Exception e => e -> IO a
throwIO (FinalizeHTTPRequest -> IO ())
-> (Maybe String -> FinalizeHTTPRequest) -> Maybe String -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((Maybe String -> FinalizeHTTPRequest) -> Maybe String -> IO ())
-> (Int -> Maybe String -> FinalizeHTTPRequest)
-> Int
-> Maybe String
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Maybe String -> FinalizeHTTPRequest
FinalizeHTTPRequest
workerProcessIsExiting :: SomeException -> Bool
workerProcessIsExiting :: SomeException -> Bool
workerProcessIsExiting e :: SomeException
e =
Maybe WorkerProcessIsExiting -> Bool
forall a. Maybe a -> Bool
isJust (SomeException -> Maybe WorkerProcessIsExiting
forall e. Exception e => SomeException -> Maybe e
fromException SomeException
e :: Maybe WorkerProcessIsExiting)
ngxRequestPtr :: ByteString -> Ptr ()
ngxRequestPtr :: ByteString -> Ptr ()
ngxRequestPtr = WordPtr -> Ptr ()
forall a. WordPtr -> Ptr a
wordPtrToPtr (WordPtr -> Ptr ())
-> (ByteString -> WordPtr) -> ByteString -> Ptr ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> WordPtr
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> WordPtr) -> (ByteString -> Word) -> ByteString -> WordPtr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Get Word -> ByteString -> Word
forall a. Get a -> ByteString -> a
runGet Get Word
getWordhost (ByteString -> Word)
-> (ByteString -> ByteString) -> ByteString -> Word
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
L.fromStrict
ngxNow :: IO CTime
ngxNow :: IO CTime
ngxNow = IO (Ptr (Ptr ()))
ngxCachedTimePtr IO (Ptr (Ptr ())) -> (Ptr (Ptr ()) -> IO (Ptr ())) -> IO (Ptr ())
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr (Ptr ()) -> IO (Ptr ())
forall a. Storable a => Ptr a -> IO a
peek IO (Ptr ()) -> (Ptr () -> IO CTime) -> IO CTime
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Ptr CTime -> IO CTime
forall a. Storable a => Ptr a -> IO a
peek (Ptr CTime -> IO CTime)
-> (Ptr () -> Ptr CTime) -> Ptr () -> IO CTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr () -> Ptr CTime
forall a b. Ptr a -> Ptr b
castPtr
ngxPid :: IO CPid
ngxPid :: IO CPid
ngxPid = IO CPid
ngxCachedPid
data TimeInterval = Hr Int
| Min Int
| Sec Int
| HrMin Int Int
| MinSec Int Int
| Unset
deriving ((forall x. TimeInterval -> Rep TimeInterval x)
-> (forall x. Rep TimeInterval x -> TimeInterval)
-> Generic TimeInterval
forall x. Rep TimeInterval x -> TimeInterval
forall x. TimeInterval -> Rep TimeInterval x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TimeInterval x -> TimeInterval
$cfrom :: forall x. TimeInterval -> Rep TimeInterval x
Generic, TimeInterval -> Q Exp
(TimeInterval -> Q Exp) -> Lift TimeInterval
forall t. (t -> Q Exp) -> Lift t
lift :: TimeInterval -> Q Exp
$clift :: TimeInterval -> Q Exp
Lift, ReadPrec [TimeInterval]
ReadPrec TimeInterval
Int -> ReadS TimeInterval
ReadS [TimeInterval]
(Int -> ReadS TimeInterval)
-> ReadS [TimeInterval]
-> ReadPrec TimeInterval
-> ReadPrec [TimeInterval]
-> Read TimeInterval
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [TimeInterval]
$creadListPrec :: ReadPrec [TimeInterval]
readPrec :: ReadPrec TimeInterval
$creadPrec :: ReadPrec TimeInterval
readList :: ReadS [TimeInterval]
$creadList :: ReadS [TimeInterval]
readsPrec :: Int -> ReadS TimeInterval
$creadsPrec :: Int -> ReadS TimeInterval
Read, Int -> TimeInterval -> ShowS
[TimeInterval] -> ShowS
TimeInterval -> String
(Int -> TimeInterval -> ShowS)
-> (TimeInterval -> String)
-> ([TimeInterval] -> ShowS)
-> Show TimeInterval
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TimeInterval] -> ShowS
$cshowList :: [TimeInterval] -> ShowS
show :: TimeInterval -> String
$cshow :: TimeInterval -> String
showsPrec :: Int -> TimeInterval -> ShowS
$cshowsPrec :: Int -> TimeInterval -> ShowS
Show)
instance FromJSON TimeInterval
instance Eq TimeInterval where
== :: TimeInterval -> TimeInterval -> Bool
(==) = Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Int -> Int -> Bool)
-> (TimeInterval -> Int) -> TimeInterval -> TimeInterval -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` TimeInterval -> Int
toSec
instance Ord TimeInterval where
compare :: TimeInterval -> TimeInterval -> Ordering
compare = (TimeInterval -> Int) -> TimeInterval -> TimeInterval -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing TimeInterval -> Int
toSec
toSec :: TimeInterval -> Int
toSec :: TimeInterval -> Int
toSec (Hr h :: Int
h) = 3600 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
h
toSec (Min m :: Int
m) = 60 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
m
toSec (Sec s :: Int
s) = Int
s
toSec (HrMin h :: Int
h m :: Int
m) = 3600 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
h Int -> Int -> Int
forall a. Num a => a -> a -> a
+ 60 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
m
toSec (MinSec m :: Int
m s :: Int
s) = 60 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
m Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
s
toSec Unset = 0
threadDelaySec :: Int -> IO ()
threadDelaySec :: Int -> IO ()
threadDelaySec = Int -> IO ()
threadDelay (Int -> IO ()) -> (Int -> Int) -> Int -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int
forall a. Num a => a -> a -> a
* 1e6)
data Readable a
data ReadableAsJSON a
class FromByteString a where
type WrappedT a
fromByteString :: Maybe a -> ByteString -> Maybe (WrappedT a)
instance Read a => FromByteString (Readable a) where
type WrappedT (Readable a) = a
fromByteString :: Maybe (Readable a) -> ByteString -> Maybe (WrappedT (Readable a))
fromByteString = (ByteString -> Maybe a)
-> Maybe (Readable a)
-> ByteString
-> Maybe (WrappedT (Readable a))
forall a b. a -> b -> a
const ((ByteString -> Maybe a)
-> Maybe (Readable a)
-> ByteString
-> Maybe (WrappedT (Readable a)))
-> (ByteString -> Maybe a)
-> Maybe (Readable a)
-> ByteString
-> Maybe (WrappedT (Readable a))
forall a b. (a -> b) -> a -> b
$ String -> Maybe a
forall a. Read a => String -> Maybe a
readMay (String -> Maybe a)
-> (ByteString -> String) -> ByteString -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> String
C8.unpack
instance FromJSON a => FromByteString (ReadableAsJSON a) where
type WrappedT (ReadableAsJSON a) = a
fromByteString :: Maybe (ReadableAsJSON a)
-> ByteString -> Maybe (WrappedT (ReadableAsJSON a))
fromByteString = (ByteString -> Maybe a)
-> Maybe (ReadableAsJSON a) -> ByteString -> Maybe a
forall a b. a -> b -> a
const ByteString -> Maybe a
forall a. FromJSON a => ByteString -> Maybe a
decodeStrict
instance FromByteString ByteString where
type WrappedT ByteString = ByteString
fromByteString :: Maybe ByteString -> ByteString -> Maybe (WrappedT ByteString)
fromByteString = (ByteString -> Maybe ByteString)
-> Maybe ByteString -> ByteString -> Maybe ByteString
forall a b. a -> b -> a
const ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just
readFromByteString :: Read a => ByteString -> Maybe a
readFromByteString :: ByteString -> Maybe a
readFromByteString = Maybe (Readable a) -> ByteString -> Maybe (WrappedT (Readable a))
forall a.
FromByteString a =>
Maybe a -> ByteString -> Maybe (WrappedT a)
fromByteString (forall a. Maybe a
forall a. Maybe (Readable a)
Nothing :: Maybe (Readable a))
readFromByteStringAsJSON :: FromJSON a => ByteString -> Maybe a
readFromByteStringAsJSON :: ByteString -> Maybe a
readFromByteStringAsJSON = Maybe (ReadableAsJSON a)
-> ByteString -> Maybe (WrappedT (ReadableAsJSON a))
forall a.
FromByteString a =>
Maybe a -> ByteString -> Maybe (WrappedT a)
fromByteString (forall a. Maybe a
forall a. Maybe (ReadableAsJSON a)
Nothing :: Maybe (ReadableAsJSON a))
readFromByteStringWithRPtr :: Read a => ByteString -> (Ptr (), Maybe a)
readFromByteStringWithRPtr :: ByteString -> (Ptr (), Maybe a)
readFromByteStringWithRPtr = ByteString -> Ptr ()
ngxRequestPtr (ByteString -> Ptr ())
-> (ByteString -> Maybe a) -> ByteString -> (Ptr (), Maybe a)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& ByteString -> Maybe a
forall a. Read a => ByteString -> Maybe a
readFromByteString (ByteString -> Maybe a)
-> (ByteString -> ByteString) -> ByteString -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
skipRPtr
readFromByteStringWithRPtrAsJSON :: FromJSON a =>
ByteString -> (Ptr (), Maybe a)
readFromByteStringWithRPtrAsJSON :: ByteString -> (Ptr (), Maybe a)
readFromByteStringWithRPtrAsJSON =
ByteString -> Ptr ()
ngxRequestPtr (ByteString -> Ptr ())
-> (ByteString -> Maybe a) -> ByteString -> (Ptr (), Maybe a)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& ByteString -> Maybe a
forall a. FromJSON a => ByteString -> Maybe a
readFromByteStringAsJSON (ByteString -> Maybe a)
-> (ByteString -> ByteString) -> ByteString -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
skipRPtr
skipRPtr :: ByteString -> ByteString
skipRPtr :: ByteString -> ByteString
skipRPtr = Int -> ByteString -> ByteString
B.drop (Int -> ByteString -> ByteString)
-> Int -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Word -> Int
forall a. Storable a => a -> Int
sizeOf (Word
forall a. HasCallStack => a
undefined :: Word)
data ServiceMode
= PersistentService (Maybe TimeInterval)
| SingleShotService
ngxExportSimpleService' :: Name -> Maybe (Name, Bool) -> ServiceMode -> Q [Dec]
ngxExportSimpleService' :: Name -> Maybe (Name, Bool) -> ServiceMode -> Q [Dec]
ngxExportSimpleService' f :: Name
f c :: Maybe (Name, Bool)
c m :: ServiceMode
m = do
Name
confBs <- String -> Q Name
newName "confBs_"
Name
fstRun <- String -> Q Name
newName "fstRun_"
let nameF :: String
nameF = Name -> String
nameBase Name
f
nameSsf :: Name
nameSsf = String -> Name
mkName (String -> Name) -> String -> Name
forall a b. (a -> b) -> a -> b
$ "simpleService_" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
nameF
hasConf :: Bool
hasConf = Maybe (Name, Bool) -> Bool
forall a. Maybe a -> Bool
isJust Maybe (Name, Bool)
c
(sNameC :: Name
sNameC, typeC :: TypeQ
typeC, readConf :: Q Exp
readConf, unreadableConfMsg :: String
unreadableConfMsg) =
if Bool
hasConf
then let (tName :: String
tName, isJSON :: Bool
isJSON) = (Name -> String) -> (Name, Bool) -> (String, Bool)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first Name -> String
nameBase ((Name, Bool) -> (String, Bool)) -> (Name, Bool) -> (String, Bool)
forall a b. (a -> b) -> a -> b
$ Maybe (Name, Bool) -> (Name, Bool)
forall a. HasCallStack => Maybe a -> a
fromJust Maybe (Name, Bool)
c
in (String -> Name
mkName (String -> Name) -> String -> Name
forall a b. (a -> b) -> a -> b
$ "storage_" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
tName String -> ShowS
forall a. [a] -> [a] -> [a]
++ '_' Char -> ShowS
forall a. a -> [a] -> [a]
: String
nameF
,Name -> TypeQ
conT (Name -> TypeQ) -> Name -> TypeQ
forall a b. (a -> b) -> a -> b
$ String -> Name
mkName String
tName
,if Bool
isJSON
then [|readFromByteStringAsJSON|]
else [|readFromByteString|]
,"Configuration " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
tName String -> ShowS
forall a. [a] -> [a] -> [a]
++ " is not readable"
)
else (Name, TypeQ, Q Exp, String)
forall a. HasCallStack => a
undefined
initConf :: Q Exp
initConf =
let eConfBs :: Q Exp
eConfBs = Name -> Q Exp
varE Name
confBs
in if Bool
hasConf
then let storage :: Q Exp
storage = Name -> Q Exp
varE Name
sNameC
in [|readIORef $(storage) >>=
maybe
(do
let conf_data__ =
$(readConf) $(eConfBs)
when (isNothing conf_data__) $
terminateWorkerProcess
unreadableConfMsg
writeIORef $(storage) conf_data__
return conf_data__
) (return . Just)
|]
else [|return $
fromByteString (Nothing :: Maybe ByteString)
$(eConfBs)
|]
(waitTime :: Q Exp
waitTime, runService :: Q Exp
runService) =
let eF :: Q Exp
eF = Name -> Q Exp
varE Name
f
eFstRun :: Q Exp
eFstRun = Name -> Q Exp
varE Name
fstRun
runPersistentService :: Q Exp
runPersistentService = [|flip $(eF) $(eFstRun)|]
in case ServiceMode
m of
PersistentService (Just t :: TimeInterval
t) ->
([|const $ unless $(eFstRun) $ threadDelaySec $ toSec t|]
,Q Exp
runPersistentService
)
PersistentService Nothing ->
([|const $ return ()|]
,Q Exp
runPersistentService
)
SingleShotService ->
([|\conf_data__ -> unless $(eFstRun) $
handle
(const $ void $ $(eF) conf_data__ False ::
WorkerProcessIsExiting -> IO ()
) $ forever $ threadDelaySec $ toSec $ Hr 24
|]
,[|\conf_data__ ->
if $(eFstRun)
then $(eF) conf_data__ True
else return L.empty
|]
)
[[Dec]] -> [Dec]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Dec]] -> [Dec]) -> Q [[Dec]] -> Q [Dec]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Q [Dec]] -> Q [[Dec]]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence
[[Q Dec] -> Q [Dec]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Q Dec] -> Q [Dec]) -> [Q Dec] -> Q [Dec]
forall a b. (a -> b) -> a -> b
$
(if Bool
hasConf
then [Name -> TypeQ -> Q Dec
sigD Name
sNameC [t|IORef (Maybe $(typeC))|]
,Name -> [ClauseQ] -> Q Dec
funD Name
sNameC
[[PatQ] -> BodyQ -> [Q Dec] -> ClauseQ
clause []
(Q Exp -> BodyQ
normalB [|unsafePerformIO $ newIORef Nothing|])
[]
]
,Name -> Inline -> RuleMatch -> Phases -> Q Dec
pragInlD Name
sNameC Inline
NoInline RuleMatch
FunLike Phases
AllPhases
]
else []
)
[Q Dec] -> [Q Dec] -> [Q Dec]
forall a. [a] -> [a] -> [a]
++
[Name -> TypeQ -> Q Dec
sigD Name
nameSsf [t|ByteString -> Bool -> IO L.ByteString|]
,Name -> [ClauseQ] -> Q Dec
funD Name
nameSsf
[[PatQ] -> BodyQ -> [Q Dec] -> ClauseQ
clause [Name -> PatQ
varP Name
confBs, Name -> PatQ
varP Name
fstRun]
(Q Exp -> BodyQ
normalB [|do
conf_data_ <- fromJust <$> $(initConf)
$(waitTime) conf_data_
$(runService) conf_data_
|]
)
[]
]
]
,Name -> Q [Dec]
ngxExportServiceIOYY Name
nameSsf
]
ngxExportSimpleService :: Name
-> ServiceMode
-> Q [Dec]
ngxExportSimpleService :: Name -> ServiceMode -> Q [Dec]
ngxExportSimpleService f :: Name
f =
Name -> Maybe (Name, Bool) -> ServiceMode -> Q [Dec]
ngxExportSimpleService' Name
f Maybe (Name, Bool)
forall a. Maybe a
Nothing
ngxExportSimpleServiceTyped :: Name
-> Name
-> ServiceMode
-> Q [Dec]
ngxExportSimpleServiceTyped :: Name -> Name -> ServiceMode -> Q [Dec]
ngxExportSimpleServiceTyped f :: Name
f c :: Name
c =
Name -> Maybe (Name, Bool) -> ServiceMode -> Q [Dec]
ngxExportSimpleService' Name
f (Maybe (Name, Bool) -> ServiceMode -> Q [Dec])
-> Maybe (Name, Bool) -> ServiceMode -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ (Name, Bool) -> Maybe (Name, Bool)
forall a. a -> Maybe a
Just (Name
c, Bool
False)
ngxExportSimpleServiceTypedAsJSON :: Name
-> Name
-> ServiceMode
-> Q [Dec]
ngxExportSimpleServiceTypedAsJSON :: Name -> Name -> ServiceMode -> Q [Dec]
ngxExportSimpleServiceTypedAsJSON f :: Name
f c :: Name
c =
Name -> Maybe (Name, Bool) -> ServiceMode -> Q [Dec]
ngxExportSimpleService' Name
f (Maybe (Name, Bool) -> ServiceMode -> Q [Dec])
-> Maybe (Name, Bool) -> ServiceMode -> Q [Dec]
forall a b. (a -> b) -> a -> b
$ (Name, Bool) -> Maybe (Name, Bool)
forall a. a -> Maybe a
Just (Name
c, Bool
True)
splitService :: (a -> IO L.ByteString)
-> (a -> IO L.ByteString)
-> a
-> Bool
-> IO L.ByteString
splitService :: (a -> IO ByteString)
-> (a -> IO ByteString) -> a -> Bool -> IO ByteString
splitService is :: a -> IO ByteString
is ds :: a -> IO ByteString
ds c :: a
c fstRun :: Bool
fstRun
| Bool
fstRun = a -> IO ByteString
is a
c
| Bool
otherwise = a -> IO ByteString
ds a
c
ignitionService :: (a -> IO L.ByteString)
-> a
-> Bool
-> IO L.ByteString
ignitionService :: (a -> IO ByteString) -> a -> Bool -> IO ByteString
ignitionService is :: a -> IO ByteString
is = (a -> IO ByteString)
-> (a -> IO ByteString) -> a -> Bool -> IO ByteString
forall a.
(a -> IO ByteString)
-> (a -> IO ByteString) -> a -> Bool -> IO ByteString
splitService a -> IO ByteString
is ((a -> IO ByteString) -> a -> Bool -> IO ByteString)
-> (a -> IO ByteString) -> a -> Bool -> IO ByteString
forall a b. (a -> b) -> a -> b
$ IO ByteString -> a -> IO ByteString
forall a b. a -> b -> a
const (IO ByteString -> a -> IO ByteString)
-> IO ByteString -> a -> IO ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
L.empty
deferredService :: (a -> IO L.ByteString)
-> a
-> Bool
-> IO L.ByteString
deferredService :: (a -> IO ByteString) -> a -> Bool -> IO ByteString
deferredService = (a -> IO ByteString)
-> (a -> IO ByteString) -> a -> Bool -> IO ByteString
forall a.
(a -> IO ByteString)
-> (a -> IO ByteString) -> a -> Bool -> IO ByteString
splitService ((a -> IO ByteString)
-> (a -> IO ByteString) -> a -> Bool -> IO ByteString)
-> (a -> IO ByteString)
-> (a -> IO ByteString)
-> a
-> Bool
-> IO ByteString
forall a b. (a -> b) -> a -> b
$ IO ByteString -> a -> IO ByteString
forall a b. a -> b -> a
const (IO ByteString -> a -> IO ByteString)
-> IO ByteString -> a -> IO ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
L.empty