{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Network.Wait (
waitTcp,
waitTcpVerbose,
waitTcpVerboseFormat,
waitTcpWith,
waitSocket,
waitSocketVerbose,
waitSocketVerboseFormat,
waitSocketWith
) where
import Control.Monad.Catch
import Control.Monad.IO.Class
import Control.Retry
import Network.Socket
waitTcp
:: (MonadIO m, MonadMask m)
=> RetryPolicyM m -> HostName -> ServiceName -> m ()
waitTcp :: RetryPolicyM m -> HostName -> HostName -> m ()
waitTcp = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m ()
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m ()
waitTcpWith []
waitTcpVerbose
:: (MonadIO m, MonadMask m)
=> (String -> m ()) -> RetryPolicyM m -> HostName -> ServiceName -> m ()
waitTcpVerbose :: (HostName -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m ()
waitTcpVerbose HostName -> m ()
out =
forall e (m :: * -> *).
(MonadIO m, MonadMask m, Exception e) =>
(Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m ()
forall (m :: * -> *).
(MonadIO m, MonadMask m, Exception SomeException) =>
(Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m ()
waitTcpVerboseFormat @SomeException ((Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m ())
-> (Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m
-> HostName
-> HostName
-> m ()
forall a b. (a -> b) -> a -> b
$
\Bool
b SomeException
ex RetryStatus
st -> HostName -> m ()
out (HostName -> m ()) -> HostName -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> SomeException -> RetryStatus -> HostName
forall e. Exception e => Bool -> e -> RetryStatus -> HostName
defaultLogMsg Bool
b SomeException
ex RetryStatus
st
waitTcpVerboseFormat
:: forall e m . (MonadIO m, MonadMask m, Exception e)
=> (Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m
-> HostName
-> ServiceName
-> m ()
waitTcpVerboseFormat :: (Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m ()
waitTcpVerboseFormat Bool -> e -> RetryStatus -> m ()
out = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m ()
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m ()
waitTcpWith [RetryStatus -> Handler m Bool
h]
where h :: RetryStatus -> Handler m Bool
h = (e -> m Bool)
-> (Bool -> e -> RetryStatus -> m ())
-> RetryStatus
-> Handler m Bool
forall (m :: * -> *) e.
(Monad m, Exception e) =>
(e -> m Bool)
-> (Bool -> e -> RetryStatus -> m ())
-> RetryStatus
-> Handler m Bool
logRetries (m Bool -> e -> m Bool
forall a b. a -> b -> a
const (m Bool -> e -> m Bool) -> m Bool -> e -> m Bool
forall a b. (a -> b) -> a -> b
$ Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True) Bool -> e -> RetryStatus -> m ()
out
waitTcpWith
:: (MonadIO m, MonadMask m)
=> [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> ServiceName -> m ()
waitTcpWith :: [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m ()
waitTcpWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy HostName
host HostName
port = do
let hints :: AddrInfo
hints = AddrInfo
defaultHints { addrSocketType :: SocketType
addrSocketType = SocketType
Stream }
AddrInfo
addr <- [AddrInfo] -> AddrInfo
forall a. [a] -> a
head ([AddrInfo] -> AddrInfo) -> m [AddrInfo] -> m AddrInfo
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO [AddrInfo] -> m [AddrInfo]
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Maybe AddrInfo -> Maybe HostName -> Maybe HostName -> IO [AddrInfo]
getAddrInfo (AddrInfo -> Maybe AddrInfo
forall a. a -> Maybe a
Just AddrInfo
hints) (HostName -> Maybe HostName
forall a. a -> Maybe a
Just HostName
host) (HostName -> Maybe HostName
forall a. a -> Maybe a
Just HostName
port))
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m ()
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m ()
waitSocketWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy AddrInfo
addr
waitSocket
:: (MonadIO m, MonadMask m)
=> RetryPolicyM m -> AddrInfo -> m ()
waitSocket :: RetryPolicyM m -> AddrInfo -> m ()
waitSocket = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m ()
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m ()
waitSocketWith []
waitSocketVerbose
:: (MonadIO m, MonadMask m)
=> (String -> m ()) -> RetryPolicyM m -> AddrInfo -> m ()
waitSocketVerbose :: (HostName -> m ()) -> RetryPolicyM m -> AddrInfo -> m ()
waitSocketVerbose HostName -> m ()
out =
forall e (m :: * -> *).
(MonadIO m, MonadMask m, Exception e) =>
(Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> AddrInfo -> m ()
forall (m :: * -> *).
(MonadIO m, MonadMask m, Exception SomeException) =>
(Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> AddrInfo -> m ()
waitSocketVerboseFormat @SomeException ((Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> AddrInfo -> m ())
-> (Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m
-> AddrInfo
-> m ()
forall a b. (a -> b) -> a -> b
$
\Bool
b SomeException
ex RetryStatus
st -> HostName -> m ()
out (HostName -> m ()) -> HostName -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> SomeException -> RetryStatus -> HostName
forall e. Exception e => Bool -> e -> RetryStatus -> HostName
defaultLogMsg Bool
b SomeException
ex RetryStatus
st
waitSocketVerboseFormat
:: forall e m . (MonadIO m, MonadMask m, Exception e)
=> (Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m
-> AddrInfo
-> m ()
waitSocketVerboseFormat :: (Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> AddrInfo -> m ()
waitSocketVerboseFormat Bool -> e -> RetryStatus -> m ()
out = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m ()
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m ()
waitSocketWith [RetryStatus -> Handler m Bool
h]
where h :: RetryStatus -> Handler m Bool
h = (e -> m Bool)
-> (Bool -> e -> RetryStatus -> m ())
-> RetryStatus
-> Handler m Bool
forall (m :: * -> *) e.
(Monad m, Exception e) =>
(e -> m Bool)
-> (Bool -> e -> RetryStatus -> m ())
-> RetryStatus
-> Handler m Bool
logRetries (m Bool -> e -> m Bool
forall a b. a -> b -> a
const (m Bool -> e -> m Bool) -> m Bool -> e -> m Bool
forall a b. (a -> b) -> a -> b
$ Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True) Bool -> e -> RetryStatus -> m ()
out
waitSocketWith
:: (MonadIO m, MonadMask m)
=> [RetryStatus -> Handler m Bool] -> RetryPolicyM m -> AddrInfo -> m ()
waitSocketWith :: [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m ()
waitSocketWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy AddrInfo
addr =
RetryPolicyM m
-> [RetryStatus -> Handler m Bool] -> (RetryStatus -> m ()) -> m ()
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
RetryPolicyM m
-> [RetryStatus -> Handler m Bool] -> (RetryStatus -> m a) -> m a
recovering RetryPolicyM m
policy ([RetryStatus -> Handler m Bool]
forall (m :: * -> *). MonadIO m => [RetryStatus -> Handler m Bool]
skipAsyncExceptions [RetryStatus -> Handler m Bool]
-> [RetryStatus -> Handler m Bool]
-> [RetryStatus -> Handler m Bool]
forall a. Semigroup a => a -> a -> a
<> [RetryStatus -> Handler m Bool]
hs [RetryStatus -> Handler m Bool]
-> [RetryStatus -> Handler m Bool]
-> [RetryStatus -> Handler m Bool]
forall a. Semigroup a => a -> a -> a
<> [RetryStatus -> Handler m Bool
forall (m :: * -> *) p. Applicative m => p -> Handler m Bool
defHandler])((RetryStatus -> m ()) -> m ()) -> (RetryStatus -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \RetryStatus
_ ->
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$
IO Socket -> (Socket -> IO ()) -> (Socket -> IO ()) -> IO ()
forall (m :: * -> *) a c b.
MonadMask m =>
m a -> (a -> m c) -> (a -> m b) -> m b
bracket IO Socket
initSocket Socket -> IO ()
close ((Socket -> IO ()) -> IO ()) -> (Socket -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$
\Socket
sock -> Socket -> SockAddr -> IO ()
connect Socket
sock (AddrInfo -> SockAddr
addrAddress AddrInfo
addr)
where
initSocket :: IO Socket
initSocket =
Family -> SocketType -> ProtocolNumber -> IO Socket
socket (AddrInfo -> Family
addrFamily AddrInfo
addr) (AddrInfo -> SocketType
addrSocketType AddrInfo
addr) (AddrInfo -> ProtocolNumber
addrProtocol AddrInfo
addr)
defHandler :: p -> Handler m Bool
defHandler p
_ = (SomeException -> m Bool) -> Handler m Bool
forall (m :: * -> *) a e. Exception e => (e -> m a) -> Handler m a
Handler ((SomeException -> m Bool) -> Handler m Bool)
-> (SomeException -> m Bool) -> Handler m Bool
forall a b. (a -> b) -> a -> b
$ \(SomeException
_ :: SomeException) -> Bool -> m Bool
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True