{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
module Ouroboros.Network.PeerSelection.RootPeersDNS.LocalRootPeers
(
localRootPeersProvider
, TraceLocalRootPeers (..)
) where
import Data.List.NonEmpty (NonEmpty (..))
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Void (Void, absurd)
import Data.Word (Word32)
import Control.Applicative (Alternative, (<|>))
import Control.Concurrent.Class.MonadSTM.Strict
import Control.Monad (when)
import Control.Monad.Class.MonadAsync
import Control.Monad.Class.MonadThrow
import Control.Monad.Class.MonadTime.SI
import Control.Monad.Class.MonadTimer.SI
import Control.Tracer (Tracer (..), contramap, traceWith)
import Network.DNS qualified as DNS
import Data.Bifunctor (second)
import Ouroboros.Network.PeerSelection.RelayAccessPoint
import Ouroboros.Network.PeerSelection.RootPeersDNS (PeerActionsDNS (..))
import Ouroboros.Network.PeerSelection.RootPeersDNS.DNSActions
import Ouroboros.Network.PeerSelection.RootPeersDNS.DNSSemaphore (DNSSemaphore,
newDNSLocalRootSemaphore, withDNSSemaphore)
import Ouroboros.Network.PeerSelection.State.LocalRootPeers (HotValency,
LocalRootConfig, WarmValency)
import Ouroboros.Network.PeerSelection.State.LocalRootPeers qualified as LocalRootPeers
data TraceLocalRootPeers extraFlags peerAddr exception =
TraceLocalRootDomains (LocalRootPeers.Config extraFlags RelayAccessPoint)
| TraceLocalRootWaiting DomainAccessPoint DiffTime
| TraceLocalRootResult DomainAccessPoint [(IP, DNS.TTL)]
| TraceLocalRootGroups (LocalRootPeers.Config extraFlags peerAddr)
| TraceLocalRootDNSMap (Map DomainAccessPoint [peerAddr])
| TraceLocalRootReconfigured (LocalRootPeers.Config extraFlags RelayAccessPoint)
(LocalRootPeers.Config extraFlags RelayAccessPoint)
| TraceLocalRootFailure DomainAccessPoint (DNSorIOError exception)
| TraceLocalRootError DomainAccessPoint SomeException
deriving Int -> TraceLocalRootPeers extraFlags peerAddr exception -> ShowS
[TraceLocalRootPeers extraFlags peerAddr exception] -> ShowS
TraceLocalRootPeers extraFlags peerAddr exception -> String
(Int -> TraceLocalRootPeers extraFlags peerAddr exception -> ShowS)
-> (TraceLocalRootPeers extraFlags peerAddr exception -> String)
-> ([TraceLocalRootPeers extraFlags peerAddr exception] -> ShowS)
-> Show (TraceLocalRootPeers extraFlags peerAddr exception)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall extraFlags peerAddr exception.
(Show extraFlags, Show peerAddr, Show exception) =>
Int -> TraceLocalRootPeers extraFlags peerAddr exception -> ShowS
forall extraFlags peerAddr exception.
(Show extraFlags, Show peerAddr, Show exception) =>
[TraceLocalRootPeers extraFlags peerAddr exception] -> ShowS
forall extraFlags peerAddr exception.
(Show extraFlags, Show peerAddr, Show exception) =>
TraceLocalRootPeers extraFlags peerAddr exception -> String
$cshowsPrec :: forall extraFlags peerAddr exception.
(Show extraFlags, Show peerAddr, Show exception) =>
Int -> TraceLocalRootPeers extraFlags peerAddr exception -> ShowS
showsPrec :: Int -> TraceLocalRootPeers extraFlags peerAddr exception -> ShowS
$cshow :: forall extraFlags peerAddr exception.
(Show extraFlags, Show peerAddr, Show exception) =>
TraceLocalRootPeers extraFlags peerAddr exception -> String
show :: TraceLocalRootPeers extraFlags peerAddr exception -> String
$cshowList :: forall extraFlags peerAddr exception.
(Show extraFlags, Show peerAddr, Show exception) =>
[TraceLocalRootPeers extraFlags peerAddr exception] -> ShowS
showList :: [TraceLocalRootPeers extraFlags peerAddr exception] -> ShowS
Show
localRootPeersProvider
:: forall m extraFlags peerAddr resolver exception.
( Alternative (STM m)
, MonadAsync m
, MonadDelay m
, MonadThrow m
, Ord peerAddr
, Eq extraFlags
)
=> Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
-> PeerActionsDNS peerAddr resolver exception m
-> DNS.ResolvConf
-> STM m [( HotValency
, WarmValency
, Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> StrictTVar m [( HotValency
, WarmValency
, Map peerAddr (LocalRootConfig extraFlags))]
-> m Void
localRootPeersProvider :: forall (m :: * -> *) extraFlags peerAddr resolver exception.
(Alternative (STM m), MonadAsync m, MonadDelay m, MonadThrow m,
Ord peerAddr, Eq extraFlags) =>
Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
-> PeerActionsDNS peerAddr resolver exception m
-> ResolvConf
-> STM
m
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> StrictTVar
m
[(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))]
-> m Void
localRootPeersProvider Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
tracer
PeerActionsDNS {
paToPeerAddr :: forall peeraddr resolver exception (m :: * -> *).
PeerActionsDNS peeraddr resolver exception m
-> IP -> PortNumber -> peeraddr
paToPeerAddr = IP -> PortNumber -> peerAddr
toPeerAddr,
paDnsActions :: forall peeraddr resolver exception (m :: * -> *).
PeerActionsDNS peeraddr resolver exception m
-> DNSActions resolver exception m
paDnsActions = DNSActions {
ResolvConf
-> m (Resource m (Either (DNSorIOError exception) resolver))
dnsAsyncResolverResource :: ResolvConf
-> m (Resource m (Either (DNSorIOError exception) resolver))
dnsAsyncResolverResource :: forall resolver exception (m :: * -> *).
DNSActions resolver exception m
-> ResolvConf
-> m (Resource m (Either (DNSorIOError exception) resolver))
dnsAsyncResolverResource,
ResolvConf -> resolver -> Domain -> m ([DNSError], [(IP, Word32)])
dnsLookupWithTTL :: ResolvConf -> resolver -> Domain -> m ([DNSError], [(IP, Word32)])
dnsLookupWithTTL :: forall resolver exception (m :: * -> *).
DNSActions resolver exception m
-> ResolvConf
-> resolver
-> Domain
-> m ([DNSError], [(IP, Word32)])
dnsLookupWithTTL
}
}
ResolvConf
resolvConf
STM
m
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
readLocalRootPeers
StrictTVar
m
[(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))]
rootPeersGroupVar =
STM
m
(DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m (DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (do domainsGroups <- STM
m
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
readLocalRootPeers
writeTVar rootPeersGroupVar (getLocalRootPeersGroups Map.empty domainsGroups)
dnsSemaphore <- newDNSLocalRootSemaphore
return (dnsSemaphore, domainsGroups))
m (DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> ((DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m Void)
-> m Void
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (DNSSemaphore m
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m Void)
-> (DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m Void
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry DNSSemaphore m
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m Void
loop
where
loop :: DNSSemaphore m
-> [(HotValency, WarmValency, Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m Void
loop :: DNSSemaphore m
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m Void
loop DNSSemaphore m
dnsSemaphore [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups = do
Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
-> TraceLocalRootPeers extraFlags peerAddr exception -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
tracer ([(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> TraceLocalRootPeers extraFlags peerAddr exception
forall extraFlags peerAddr exception.
Config extraFlags RelayAccessPoint
-> TraceLocalRootPeers extraFlags peerAddr exception
TraceLocalRootDomains [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups)
rr <- ResolvConf
-> m (Resource m (Either (DNSorIOError exception) resolver))
dnsAsyncResolverResource ResolvConf
resolvConf
let
domains :: [DomainAccessPoint]
domains = [ DomainAccessPoint
domain
| (HotValency
_, WarmValency
_, Map RelayAccessPoint (LocalRootConfig extraFlags)
m) <- [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups
, (RelayDomainAccessPoint DomainAccessPoint
domain, LocalRootConfig extraFlags
_) <- Map RelayAccessPoint (LocalRootConfig extraFlags)
-> [(RelayAccessPoint, LocalRootConfig extraFlags)]
forall k a. Map k a -> [(k, a)]
Map.toList Map RelayAccessPoint (LocalRootConfig extraFlags)
m ]
initialDNSDomainMap :: Map DomainAccessPoint [peerAddr]
initialDNSDomainMap =
[(DomainAccessPoint, [peerAddr])]
-> Map DomainAccessPoint [peerAddr]
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(DomainAccessPoint, [peerAddr])]
-> Map DomainAccessPoint [peerAddr])
-> [(DomainAccessPoint, [peerAddr])]
-> Map DomainAccessPoint [peerAddr]
forall a b. (a -> b) -> a -> b
$ (DomainAccessPoint -> (DomainAccessPoint, [peerAddr]))
-> [DomainAccessPoint] -> [(DomainAccessPoint, [peerAddr])]
forall a b. (a -> b) -> [a] -> [b]
map (, []) [DomainAccessPoint]
domains
dnsDomainMapVar <- newTVarIO initialDNSDomainMap
traceWith tracer (TraceLocalRootDNSMap initialDNSDomainMap)
domainsGroups' <-
withAsyncAllWithCtx (monitorDomain rr dnsSemaphore dnsDomainMapVar `map` domains) $ \[(DomainAccessPoint, Async m Void)]
as -> do
let tagErrWithDomain :: (t, b, Either a Void) -> Either (t, a) b
tagErrWithDomain (t
domain, b
_, Either a Void
res) = (a -> Either (t, a) b)
-> (Void -> Either (t, a) b) -> Either a Void -> Either (t, a) b
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((t, a) -> Either (t, a) b
forall a b. a -> Either a b
Left ((t, a) -> Either (t, a) b)
-> (a -> (t, a)) -> a -> Either (t, a) b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (t
domain,)) Void -> Either (t, a) b
forall a. Void -> a
absurd Either a Void
res
res <- STM
m
(Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m (Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM
m
(Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m (Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]))
-> STM
m
(Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m (Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
forall a b. (a -> b) -> a -> b
$
((DomainAccessPoint, Async m Void, Either SomeException Void)
-> Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
forall {t} {b} {a} {b}. (t, b, Either a Void) -> Either (t, a) b
tagErrWithDomain ((DomainAccessPoint, Async m Void, Either SomeException Void)
-> Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> STM
m (DomainAccessPoint, Async m Void, Either SomeException Void)
-> STM
m
(Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(DomainAccessPoint, Async m Void)]
-> STM
m (DomainAccessPoint, Async m Void, Either SomeException Void)
forall (m :: * -> *) ctx a.
MonadAsync m =>
[(ctx, Async m a)]
-> STM m (ctx, Async m a, Either SomeException a)
waitAnyCatchSTMWithCtx [(DomainAccessPoint, Async m Void)]
as)
STM
m
(Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> STM
m
(Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> STM
m
(Either
(DomainAccessPoint, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
forall a. STM m a -> STM m a -> STM m a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
(do a <- STM
m
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
readLocalRootPeers
check (a /= domainsGroups)
return (Right a))
case res of
Left (DomainAccessPoint
domain, SomeException
err) -> Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
-> TraceLocalRootPeers extraFlags peerAddr exception -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
tracer (DomainAccessPoint
-> SomeException
-> TraceLocalRootPeers extraFlags peerAddr exception
forall extraFlags peerAddr exception.
DomainAccessPoint
-> SomeException
-> TraceLocalRootPeers extraFlags peerAddr exception
TraceLocalRootError DomainAccessPoint
domain SomeException
err)
m ()
-> m [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups
Right [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups' -> Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
-> TraceLocalRootPeers extraFlags peerAddr exception -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
tracer ([(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> TraceLocalRootPeers extraFlags peerAddr exception
forall extraFlags peerAddr exception.
Config extraFlags RelayAccessPoint
-> Config extraFlags RelayAccessPoint
-> TraceLocalRootPeers extraFlags peerAddr exception
TraceLocalRootReconfigured [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups')
m ()
-> m [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups'
loop dnsSemaphore domainsGroups'
resolveDomain
:: DNSSemaphore m
-> resolver
-> DomainAccessPoint
-> m (Either [DNS.DNSError] [(peerAddr, DNS.TTL)])
resolveDomain :: DNSSemaphore m
-> resolver
-> DomainAccessPoint
-> m (Either [DNSError] [(peerAddr, Word32)])
resolveDomain DNSSemaphore m
dnsSemaphore resolver
resolver
domain :: DomainAccessPoint
domain@DomainAccessPoint {Domain
dapDomain :: Domain
dapDomain :: DomainAccessPoint -> Domain
dapDomain, PortNumber
dapPortNumber :: PortNumber
dapPortNumber :: DomainAccessPoint -> PortNumber
dapPortNumber} = do
(errs, results) <- DNSSemaphore m
-> m ([DNSError], [(IP, Word32)]) -> m ([DNSError], [(IP, Word32)])
forall (m :: * -> *) a.
(MonadSTM m, MonadThrow m) =>
DNSSemaphore m -> m a -> m a
withDNSSemaphore DNSSemaphore m
dnsSemaphore
(ResolvConf -> resolver -> Domain -> m ([DNSError], [(IP, Word32)])
dnsLookupWithTTL
ResolvConf
resolvConf
resolver
resolver
Domain
dapDomain)
mapM_ (traceWith tracer . TraceLocalRootFailure domain . DNSError)
errs
if null errs
then do
traceWith tracer (TraceLocalRootResult domain results)
return $ Right [ ( toPeerAddr addr dapPortNumber
, _ttl)
| (addr, _ttl) <- results ]
else return $ Left errs
monitorDomain
:: Resource m (Either (DNSorIOError exception) resolver)
-> DNSSemaphore m
-> StrictTVar m (Map DomainAccessPoint [peerAddr])
-> DomainAccessPoint
-> (DomainAccessPoint, m Void)
monitorDomain :: Resource m (Either (DNSorIOError exception) resolver)
-> DNSSemaphore m
-> StrictTVar m (Map DomainAccessPoint [peerAddr])
-> DomainAccessPoint
-> (DomainAccessPoint, m Void)
monitorDomain Resource m (Either (DNSorIOError exception) resolver)
rr0 DNSSemaphore m
dnsSemaphore StrictTVar m (Map DomainAccessPoint [peerAddr])
dnsDomainMapVar DomainAccessPoint
domain =
(DomainAccessPoint
domain, DiffTime -> Resource m resolver -> m Void
go DiffTime
0 (Tracer m (DNSorIOError exception)
-> NonEmpty DiffTime
-> Resource m (Either (DNSorIOError exception) resolver)
-> Resource m resolver
forall (m :: * -> *) e a.
MonadDelay m =>
Tracer m e
-> NonEmpty DiffTime -> Resource m (Either e a) -> Resource m a
retryResource (DomainAccessPoint
-> DNSorIOError exception
-> TraceLocalRootPeers extraFlags peerAddr exception
forall extraFlags peerAddr exception.
DomainAccessPoint
-> DNSorIOError exception
-> TraceLocalRootPeers extraFlags peerAddr exception
TraceLocalRootFailure DomainAccessPoint
domain (DNSorIOError exception
-> TraceLocalRootPeers extraFlags peerAddr exception)
-> Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
-> Tracer m (DNSorIOError exception)
forall a' a. (a' -> a) -> Tracer m a -> Tracer m a'
forall (f :: * -> *) a' a.
Contravariant f =>
(a' -> a) -> f a -> f a'
`contramap` Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
tracer)
(DiffTime
1 DiffTime -> [DiffTime] -> NonEmpty DiffTime
forall a. a -> [a] -> NonEmpty a
:| [DiffTime
3, DiffTime
6, DiffTime
9, DiffTime
12])
Resource m (Either (DNSorIOError exception) resolver)
rr0))
where
go :: DiffTime
-> Resource m resolver
-> m Void
go :: DiffTime -> Resource m resolver -> m Void
go !DiffTime
ttl !Resource m resolver
rr = do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (DiffTime
ttl DiffTime -> DiffTime -> Bool
forall a. Ord a => a -> a -> Bool
> DiffTime
0) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
-> TraceLocalRootPeers extraFlags peerAddr exception -> m ()
forall (m :: * -> *) a. Tracer m a -> a -> m ()
traceWith Tracer m (TraceLocalRootPeers extraFlags peerAddr exception)
tracer (DomainAccessPoint
-> DiffTime -> TraceLocalRootPeers extraFlags peerAddr exception
forall extraFlags peerAddr exception.
DomainAccessPoint
-> DiffTime -> TraceLocalRootPeers extraFlags peerAddr exception
TraceLocalRootWaiting DomainAccessPoint
domain DiffTime
ttl)
DiffTime -> m ()
forall (m :: * -> *). MonadDelay m => DiffTime -> m ()
threadDelay DiffTime
ttl
(resolver, rr') <- Resource m resolver -> m (resolver, Resource m resolver)
forall (m :: * -> *) a. Resource m a -> m (a, Resource m a)
withResource Resource m resolver
rr
reply <- resolveDomain dnsSemaphore resolver domain
case reply of
Left [DNSError]
errs -> DiffTime -> Resource m resolver -> m Void
go ([DiffTime] -> DiffTime
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([DiffTime] -> DiffTime) -> [DiffTime] -> DiffTime
forall a b. (a -> b) -> a -> b
$ (DNSError -> DiffTime) -> [DNSError] -> [DiffTime]
forall a b. (a -> b) -> [a] -> [b]
map (\DNSError
err -> DNSError -> DiffTime -> DiffTime
ttlForDnsError DNSError
err DiffTime
ttl) [DNSError]
errs)
Resource m resolver
rr'
Right [(peerAddr, Word32)]
results -> do
(newRootPeersGroups, newDNSDomainMap) <- STM
m
([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map DomainAccessPoint [peerAddr])
-> m ([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map DomainAccessPoint [peerAddr])
forall a. HasCallStack => STM m a -> m a
forall (m :: * -> *) a.
(MonadSTM m, HasCallStack) =>
STM m a -> m a
atomically (STM
m
([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map DomainAccessPoint [peerAddr])
-> m ([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map DomainAccessPoint [peerAddr]))
-> STM
m
([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map DomainAccessPoint [peerAddr])
-> m ([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map DomainAccessPoint [peerAddr])
forall a b. (a -> b) -> a -> b
$ do
dnsDomainMap <- StrictTVar m (Map DomainAccessPoint [peerAddr])
-> STM m (Map DomainAccessPoint [peerAddr])
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar StrictTVar m (Map DomainAccessPoint [peerAddr])
dnsDomainMapVar
let results' = ((peerAddr, Word32) -> peerAddr)
-> [(peerAddr, Word32)] -> [peerAddr]
forall a b. (a -> b) -> [a] -> [b]
map (peerAddr, Word32) -> peerAddr
forall a b. (a, b) -> a
fst [(peerAddr, Word32)]
results
newDNSDomainMap =
DomainAccessPoint
-> [peerAddr]
-> Map DomainAccessPoint [peerAddr]
-> Map DomainAccessPoint [peerAddr]
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert DomainAccessPoint
domain [peerAddr]
results' Map DomainAccessPoint [peerAddr]
dnsDomainMap
when (results' /= dnsDomainMap Map.! domain) $
writeTVar dnsDomainMapVar newDNSDomainMap
staticRootPeersGroups <- readLocalRootPeers
oldRootPeersGroups <- readTVar rootPeersGroupVar
let newRootPeersGroups =
Map DomainAccessPoint [peerAddr]
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> [(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))]
getLocalRootPeersGroups Map DomainAccessPoint [peerAddr]
newDNSDomainMap
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
staticRootPeersGroups
when (oldRootPeersGroups /= newRootPeersGroups) $
writeTVar rootPeersGroupVar newRootPeersGroups
return (newRootPeersGroups, newDNSDomainMap)
traceWith tracer (TraceLocalRootGroups newRootPeersGroups)
traceWith tracer (TraceLocalRootDNSMap newDNSDomainMap)
go (ttlForResults (map snd results)) rr'
getLocalRootPeersGroups :: Map DomainAccessPoint [peerAddr]
-> [( HotValency
, WarmValency
, Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> [( HotValency
, WarmValency
, Map peerAddr (LocalRootConfig extraFlags))]
getLocalRootPeersGroups :: Map DomainAccessPoint [peerAddr]
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> [(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))]
getLocalRootPeersGroups Map DomainAccessPoint [peerAddr]
dnsMap =
((HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))
-> (HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags)))
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> [(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Map RelayAccessPoint (LocalRootConfig extraFlags)
-> Map peerAddr (LocalRootConfig extraFlags))
-> (HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))
-> (HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))
forall b c a. (b -> c) -> (HotValency, a, b) -> (HotValency, a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ((Map peerAddr (LocalRootConfig extraFlags)
-> RelayAccessPoint
-> LocalRootConfig extraFlags
-> Map peerAddr (LocalRootConfig extraFlags))
-> Map peerAddr (LocalRootConfig extraFlags)
-> Map RelayAccessPoint (LocalRootConfig extraFlags)
-> Map peerAddr (LocalRootConfig extraFlags)
forall a k b. (a -> k -> b -> a) -> a -> Map k b -> a
Map.foldlWithKey'
(\Map peerAddr (LocalRootConfig extraFlags)
accMap RelayAccessPoint
rap LocalRootConfig extraFlags
pa
-> case RelayAccessPoint
rap of
RelayAccessAddress IP
ip PortNumber
port ->
peerAddr
-> LocalRootConfig extraFlags
-> Map peerAddr (LocalRootConfig extraFlags)
-> Map peerAddr (LocalRootConfig extraFlags)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert (IP -> PortNumber -> peerAddr
toPeerAddr IP
ip PortNumber
port) LocalRootConfig extraFlags
pa Map peerAddr (LocalRootConfig extraFlags)
accMap
RelayDomainAccessPoint DomainAccessPoint
dap ->
let newEntries :: Map peerAddr (LocalRootConfig extraFlags)
newEntries = Map peerAddr (LocalRootConfig extraFlags)
-> ([(peerAddr, LocalRootConfig extraFlags)]
-> Map peerAddr (LocalRootConfig extraFlags))
-> Maybe [(peerAddr, LocalRootConfig extraFlags)]
-> Map peerAddr (LocalRootConfig extraFlags)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Map peerAddr (LocalRootConfig extraFlags)
forall k a. Map k a
Map.empty
[(peerAddr, LocalRootConfig extraFlags)]
-> Map peerAddr (LocalRootConfig extraFlags)
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
(Maybe [(peerAddr, LocalRootConfig extraFlags)]
-> Map peerAddr (LocalRootConfig extraFlags))
-> Maybe [(peerAddr, LocalRootConfig extraFlags)]
-> Map peerAddr (LocalRootConfig extraFlags)
forall a b. (a -> b) -> a -> b
$ (peerAddr -> (peerAddr, LocalRootConfig extraFlags))
-> [peerAddr] -> [(peerAddr, LocalRootConfig extraFlags)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (, LocalRootConfig extraFlags
pa)
([peerAddr] -> [(peerAddr, LocalRootConfig extraFlags)])
-> Maybe [peerAddr]
-> Maybe [(peerAddr, LocalRootConfig extraFlags)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DomainAccessPoint
-> Map DomainAccessPoint [peerAddr] -> Maybe [peerAddr]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup DomainAccessPoint
dap Map DomainAccessPoint [peerAddr]
dnsMap
in Map peerAddr (LocalRootConfig extraFlags)
accMap Map peerAddr (LocalRootConfig extraFlags)
-> Map peerAddr (LocalRootConfig extraFlags)
-> Map peerAddr (LocalRootConfig extraFlags)
forall a. Semigroup a => a -> a -> a
<> Map peerAddr (LocalRootConfig extraFlags)
newEntries
)
Map peerAddr (LocalRootConfig extraFlags)
forall k a. Map k a
Map.empty
)
)
ttlForResults :: [DNS.TTL] -> DiffTime
ttlForResults :: [Word32] -> DiffTime
ttlForResults [] = DNSError -> DiffTime -> DiffTime
ttlForDnsError DNSError
DNS.NameError DiffTime
0
ttlForResults [Word32]
ttls = DiffTime -> DiffTime
clipTTLBelow
(DiffTime -> DiffTime)
-> (Word32 -> DiffTime) -> Word32 -> DiffTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiffTime -> DiffTime
clipTTLAbove
(DiffTime -> DiffTime)
-> (Word32 -> DiffTime) -> Word32 -> DiffTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word32 -> DiffTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral :: Word32 -> DiffTime)
(Word32 -> DiffTime) -> Word32 -> DiffTime
forall a b. (a -> b) -> a -> b
$ [Word32] -> Word32
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Word32]
ttls
clipTTLAbove, clipTTLBelow :: DiffTime -> DiffTime
clipTTLBelow :: DiffTime -> DiffTime
clipTTLBelow = DiffTime -> DiffTime -> DiffTime
forall a. Ord a => a -> a -> a
max DiffTime
60
clipTTLAbove :: DiffTime -> DiffTime
clipTTLAbove = DiffTime -> DiffTime -> DiffTime
forall a. Ord a => a -> a -> a
min DiffTime
86400
ttlForDnsError :: DNS.DNSError -> DiffTime -> DiffTime
ttlForDnsError :: DNSError -> DiffTime -> DiffTime
ttlForDnsError DNSError
DNS.NameError DiffTime
_ = DiffTime
10800
ttlForDnsError DNSError
_ DiffTime
ttl = DiffTime -> DiffTime
clipTTLAbove (DiffTime
ttl DiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
* DiffTime
2 DiffTime -> DiffTime -> DiffTime
forall a. Num a => a -> a -> a
+ DiffTime
5)
withAsyncAllWithCtx :: MonadAsync m => [(ctx, m a)] -> ([(ctx, Async m a)] -> m b) -> m b
withAsyncAllWithCtx :: forall (m :: * -> *) ctx a b.
MonadAsync m =>
[(ctx, m a)] -> ([(ctx, Async m a)] -> m b) -> m b
withAsyncAllWithCtx [(ctx, m a)]
contextualized [(ctx, Async m a)] -> m b
action = [(ctx, Async m a)] -> [(ctx, m a)] -> m b
go [] [(ctx, m a)]
contextualized
where
go :: [(ctx, Async m a)] -> [(ctx, m a)] -> m b
go [(ctx, Async m a)]
as [] = [(ctx, Async m a)] -> m b
action ([(ctx, Async m a)] -> [(ctx, Async m a)]
forall a. [a] -> [a]
reverse [(ctx, Async m a)]
as)
go [(ctx, Async m a)]
as ((ctx
ctx, m a
x):[(ctx, m a)]
xs) = m a -> (Async m a -> m b) -> m b
forall a b. m a -> (Async m a -> m b) -> m b
forall (m :: * -> *) a b.
MonadAsync m =>
m a -> (Async m a -> m b) -> m b
withAsync m a
x (\Async m a
a -> [(ctx, Async m a)] -> [(ctx, m a)] -> m b
go ((ctx
ctx, Async m a
a)(ctx, Async m a) -> [(ctx, Async m a)] -> [(ctx, Async m a)]
forall a. a -> [a] -> [a]
:[(ctx, Async m a)]
as) [(ctx, m a)]
xs)
waitAnyCatchSTMWithCtx :: MonadAsync m => [(ctx, Async m a)] -> STM m (ctx, Async m a, Either SomeException a)
waitAnyCatchSTMWithCtx :: forall (m :: * -> *) ctx a.
MonadAsync m =>
[(ctx, Async m a)]
-> STM m (ctx, Async m a, Either SomeException a)
waitAnyCatchSTMWithCtx = ((ctx, Async m a)
-> STM m (ctx, Async m a, Either SomeException a)
-> STM m (ctx, Async m a, Either SomeException a))
-> STM m (ctx, Async m a, Either SomeException a)
-> [(ctx, Async m a)]
-> STM m (ctx, Async m a, Either SomeException a)
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (STM m (ctx, Async m a, Either SomeException a)
-> STM m (ctx, Async m a, Either SomeException a)
-> STM m (ctx, Async m a, Either SomeException a)
forall a. STM m a -> STM m a -> STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a -> STM m a -> STM m a
orElse (STM m (ctx, Async m a, Either SomeException a)
-> STM m (ctx, Async m a, Either SomeException a)
-> STM m (ctx, Async m a, Either SomeException a))
-> ((ctx, Async m a)
-> STM m (ctx, Async m a, Either SomeException a))
-> (ctx, Async m a)
-> STM m (ctx, Async m a, Either SomeException a)
-> STM m (ctx, Async m a, Either SomeException a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ctx, Async m a) -> STM m (ctx, Async m a, Either SomeException a)
forall {m :: * -> *} {a} {a}.
MonadAsync m =>
(a, Async m a) -> STM m (a, Async m a, Either SomeException a)
waitWithCtx) STM m (ctx, Async m a, Either SomeException a)
forall a. STM m a
forall (m :: * -> *) a. MonadSTM m => STM m a
retry
where
waitWithCtx :: (a, Async m a) -> STM m (a, Async m a, Either SomeException a)
waitWithCtx (a
ctx, Async m a
a) =
do
r <- Async m a -> STM m (Either SomeException a)
forall a. Async m a -> STM m (Either SomeException a)
forall (m :: * -> *) a.
MonadAsync m =>
Async m a -> STM m (Either SomeException a)
waitCatchSTM Async m a
a
pure (ctx, a, r)