{-# OPTIONS_GHC -Wno-unused-imports #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Network.Wait (
waitTcp,
waitTcpVerbose,
waitTcpVerboseFormat,
waitTcpWith,
waitSocket,
waitSocketVerbose,
waitSocketVerboseFormat,
waitSocketWith,
recoveringWith
) where
import Control.Monad.Catch
import Control.Monad.IO.Class
import Control.Retry
import Data.Semigroup
import Network.Socket
waitTcp
:: (MonadIO m, MonadMask m)
=> RetryPolicyM m -> HostName -> ServiceName -> m Socket
waitTcp :: RetryPolicyM m -> HostName -> HostName -> m Socket
waitTcp = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m Socket
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m Socket
waitTcpWith []
waitTcpVerbose
:: (MonadIO m, MonadMask m)
=> (String -> m ()) -> RetryPolicyM m -> HostName -> ServiceName
-> m Socket
waitTcpVerbose :: (HostName -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m Socket
waitTcpVerbose HostName -> m ()
out =
forall e (m :: * -> *).
(MonadIO m, MonadMask m, Exception e) =>
(Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m Socket
forall (m :: * -> *).
(MonadIO m, MonadMask m, Exception SomeException) =>
(Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m Socket
waitTcpVerboseFormat @SomeException ((Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m Socket)
-> (Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m
-> HostName
-> HostName
-> m Socket
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 Socket
waitTcpVerboseFormat :: (Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> HostName -> HostName -> m Socket
waitTcpVerboseFormat Bool -> e -> RetryStatus -> m ()
out = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m Socket
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m Socket
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 Socket
waitTcpWith :: [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> HostName -> HostName -> m Socket
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 Socket
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m Socket
waitSocketWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy AddrInfo
addr
waitSocket
:: (MonadIO m, MonadMask m)
=> RetryPolicyM m -> AddrInfo -> m Socket
waitSocket :: RetryPolicyM m -> AddrInfo -> m Socket
waitSocket = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m Socket
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m Socket
waitSocketWith []
waitSocketVerbose
:: (MonadIO m, MonadMask m)
=> (String -> m ()) -> RetryPolicyM m -> AddrInfo -> m Socket
waitSocketVerbose :: (HostName -> m ()) -> RetryPolicyM m -> AddrInfo -> m Socket
waitSocketVerbose HostName -> m ()
out =
forall e (m :: * -> *).
(MonadIO m, MonadMask m, Exception e) =>
(Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> AddrInfo -> m Socket
forall (m :: * -> *).
(MonadIO m, MonadMask m, Exception SomeException) =>
(Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> AddrInfo -> m Socket
waitSocketVerboseFormat @SomeException ((Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m -> AddrInfo -> m Socket)
-> (Bool -> SomeException -> RetryStatus -> m ())
-> RetryPolicyM m
-> AddrInfo
-> m Socket
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 Socket
waitSocketVerboseFormat :: (Bool -> e -> RetryStatus -> m ())
-> RetryPolicyM m -> AddrInfo -> m Socket
waitSocketVerboseFormat Bool -> e -> RetryStatus -> m ()
out = [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m Socket
forall (m :: * -> *).
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m Socket
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 Socket
waitSocketWith :: [RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> AddrInfo -> m Socket
waitSocketWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy AddrInfo
addr =
[RetryStatus -> Handler m Bool]
-> RetryPolicyM m -> m Socket -> m Socket
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
[RetryStatus -> Handler m Bool] -> RetryPolicyM m -> m a -> m a
recoveringWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy (m Socket -> m Socket) -> m Socket -> m Socket
forall a b. (a -> b) -> a -> b
$
IO Socket -> m Socket
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Socket -> m Socket) -> IO Socket -> m Socket
forall a b. (a -> b) -> a -> b
$
IO Socket
-> (Socket -> IO ()) -> (Socket -> IO Socket) -> IO Socket
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 Socket) -> IO Socket)
-> (Socket -> IO Socket) -> IO Socket
forall a b. (a -> b) -> a -> b
$
\Socket
sock -> Socket -> SockAddr -> IO ()
connect Socket
sock (AddrInfo -> SockAddr
addrAddress AddrInfo
addr) IO () -> IO Socket -> IO Socket
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Socket -> IO Socket
forall (f :: * -> *) a. Applicative f => a -> f a
pure Socket
sock
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)
recoveringWith
:: (MonadIO m, MonadMask m)
=> [RetryStatus -> Handler m Bool] -> RetryPolicyM m -> m a -> m a
recoveringWith :: [RetryStatus -> Handler m Bool] -> RetryPolicyM m -> m a -> m a
recoveringWith [RetryStatus -> Handler m Bool]
hs RetryPolicyM m
policy m a
action =
RetryPolicyM m
-> [RetryStatus -> Handler m Bool] -> (RetryStatus -> m a) -> m a
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 a) -> m a) -> (RetryStatus -> m a) -> m a
forall a b. (a -> b) -> a -> b
$
m a -> RetryStatus -> m a
forall a b. a -> b -> a
const m a
action
where
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