{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
module Ouroboros.Network.PeerSelection.RootPeersDNS.LocalRootPeers
(
localRootPeersProvider
, TraceLocalRootPeers (..)
) where
import Data.Bifunctor (second)
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 System.Random
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 Ouroboros.Network.PeerSelection.RelayAccessPoint
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 RelayAccessPoint DiffTime
| TraceLocalRootGroups (LocalRootPeers.Config extraFlags peerAddr)
| TraceLocalRootDNSMap (Map RelayAccessPoint [peerAddr])
| TraceLocalRootReconfigured (LocalRootPeers.Config extraFlags RelayAccessPoint)
(LocalRootPeers.Config extraFlags RelayAccessPoint)
| TraceLocalRootFailure RelayAccessPoint (DNSorIOError exception)
| TraceLocalRootError DNS.Domain 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
-> StdGen
-> 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
-> StdGen
-> 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 peeraddr resolver exception m
paDnsActions = DNSActions {
ResolvConf
-> m (Resource m (Either (DNSorIOError exception) resolver))
dnsAsyncResolverResource :: ResolvConf
-> m (Resource m (Either (DNSorIOError exception) resolver))
dnsAsyncResolverResource :: forall peerAddr resolver exception (m :: * -> *).
DNSActions peerAddr resolver exception m
-> ResolvConf
-> m (Resource m (Either (DNSorIOError exception) resolver))
dnsAsyncResolverResource,
DNSPeersKind
-> RelayAccessPoint
-> ResolvConf
-> resolver
-> StdGen
-> m (DNSLookupResult peerAddr)
dnsLookupWithTTL :: DNSPeersKind
-> RelayAccessPoint
-> ResolvConf
-> resolver
-> StdGen
-> m (DNSLookupResult peerAddr)
dnsLookupWithTTL :: forall peerAddr resolver exception (m :: * -> *).
DNSActions peerAddr resolver exception m
-> DNSPeersKind
-> RelayAccessPoint
-> ResolvConf
-> resolver
-> StdGen
-> m (DNSLookupResult peerAddr)
dnsLookupWithTTL
}
}
ResolvConf
resolvConf
StdGen
rng0
STM
m
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
readLocalRootPeers
StrictTVar
m
[(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))]
rootPeersGroupVar =
STM
m
(StrictTVar m StdGen, DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m (StrictTVar m StdGen, 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)
(,,) <$> newTVar rng0 <*> newDNSLocalRootSemaphore <*> pure domainsGroups
m (StrictTVar m StdGen, DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> ((StrictTVar m StdGen, 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
>>= (StrictTVar m StdGen, DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m Void
loop'
where
loop' :: (StrictTVar m StdGen, DNSSemaphore m,
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m Void
loop' (StrictTVar m StdGen
varRng, DNSSemaphore m
sem, [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domGroups) = StrictTVar m StdGen
-> DNSSemaphore m
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m Void
loop StrictTVar m StdGen
varRng DNSSemaphore m
sem [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domGroups
loop :: StrictTVar m StdGen
-> DNSSemaphore m
-> [(HotValency, WarmValency, Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m Void
loop :: StrictTVar m StdGen
-> DNSSemaphore m
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> m Void
loop StrictTVar m StdGen
varRng 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 :: [RelayAccessPoint]
domains = [ RelayAccessPoint
rap
| (HotValency
_, WarmValency
_, Map RelayAccessPoint (LocalRootConfig extraFlags)
m) <- [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
domainsGroups
, (RelayAccessPoint
rap, LocalRootConfig extraFlags
_) <- Map RelayAccessPoint (LocalRootConfig extraFlags)
-> [(RelayAccessPoint, LocalRootConfig extraFlags)]
forall k a. Map k a -> [(k, a)]
Map.toList Map RelayAccessPoint (LocalRootConfig extraFlags)
m
, case RelayAccessPoint
rap of
RelayAccessAddress {} -> Bool
False
RelayAccessPoint
_otherwise -> Bool
True
]
initialDNSDomainMap :: Map RelayAccessPoint [peerAddr]
initialDNSDomainMap =
[(RelayAccessPoint, [peerAddr])] -> Map RelayAccessPoint [peerAddr]
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(RelayAccessPoint, [peerAddr])]
-> Map RelayAccessPoint [peerAddr])
-> [(RelayAccessPoint, [peerAddr])]
-> Map RelayAccessPoint [peerAddr]
forall a b. (a -> b) -> a -> b
$ (RelayAccessPoint -> (RelayAccessPoint, [peerAddr]))
-> [RelayAccessPoint] -> [(RelayAccessPoint, [peerAddr])]
forall a b. (a -> b) -> [a] -> [b]
map (, []) [RelayAccessPoint]
domains
dnsDomainMapVar <- newTVarIO initialDNSDomainMap
traceWith tracer (TraceLocalRootDNSMap initialDNSDomainMap)
domainsGroups' <-
withAsyncAllWithCtx (monitorDomain rr dnsSemaphore dnsDomainMapVar varRng `map` domains) $ \[(Domain, 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
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m (Either
(Domain, 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
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m (Either
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]))
-> STM
m
(Either
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> m (Either
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
forall a b. (a -> b) -> a -> b
$
((Domain, Async m Void, Either SomeException Void)
-> Either
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
forall {t} {b} {a} {b}. (t, b, Either a Void) -> Either (t, a) b
tagErrWithDomain ((Domain, Async m Void, Either SomeException Void)
-> Either
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> STM m (Domain, Async m Void, Either SomeException Void)
-> STM
m
(Either
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(Domain, Async m Void)]
-> STM m (Domain, 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 [(Domain, Async m Void)]
as)
STM
m
(Either
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> STM
m
(Either
(Domain, SomeException)
[(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))])
-> STM
m
(Either
(Domain, 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 (Domain
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 (Domain
-> SomeException
-> TraceLocalRootPeers extraFlags peerAddr exception
forall extraFlags peerAddr exception.
Domain
-> SomeException
-> TraceLocalRootPeers extraFlags peerAddr exception
TraceLocalRootError Domain
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 varRng dnsSemaphore domainsGroups'
monitorDomain
:: Resource m (Either (DNSorIOError exception) resolver)
-> DNSSemaphore m
-> StrictTVar m (Map RelayAccessPoint [peerAddr])
-> StrictTVar m StdGen
-> RelayAccessPoint
-> (DNS.Domain, m Void)
monitorDomain :: Resource m (Either (DNSorIOError exception) resolver)
-> DNSSemaphore m
-> StrictTVar m (Map RelayAccessPoint [peerAddr])
-> StrictTVar m StdGen
-> RelayAccessPoint
-> (Domain, m Void)
monitorDomain Resource m (Either (DNSorIOError exception) resolver)
rr0 DNSSemaphore m
dnsSemaphore StrictTVar m (Map RelayAccessPoint [peerAddr])
dnsDomainMapVar StrictTVar m StdGen
varRng RelayAccessPoint
domain =
(Domain
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 (RelayAccessPoint
-> DNSorIOError exception
-> TraceLocalRootPeers extraFlags peerAddr exception
forall extraFlags peerAddr exception.
RelayAccessPoint
-> DNSorIOError exception
-> TraceLocalRootPeers extraFlags peerAddr exception
TraceLocalRootFailure RelayAccessPoint
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
domain' :: Domain
domain' = case RelayAccessPoint
domain of
RelayAccessDomain Domain
d PortNumber
_p -> Domain
d
RelayAccessSRVDomain Domain
d -> Domain
d
RelayAccessPoint
_otherwise -> String -> Domain
forall a. HasCallStack => String -> a
error String
"LocalRootPeers.monitorDomain: impossible!"
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 (RelayAccessPoint
-> DiffTime -> TraceLocalRootPeers extraFlags peerAddr exception
forall extraFlags peerAddr exception.
RelayAccessPoint
-> DiffTime -> TraceLocalRootPeers extraFlags peerAddr exception
TraceLocalRootWaiting RelayAccessPoint
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
rng <- atomically . stateTVar varRng $ split
reply <- withDNSSemaphore dnsSemaphore
(dnsLookupWithTTL
DNSLocalPeer
domain
resolvConf
resolver
rng)
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 (DiffTime -> DNSError -> DiffTime
ttlForDnsError DiffTime
ttl) [DNSError]
errs)
Resource m resolver
rr'
Right [(peerAddr, Word32)]
results -> do
(newRootPeersGroups, newDNSDomainMap) <- STM
m
([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map RelayAccessPoint [peerAddr])
-> m ([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map RelayAccessPoint [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 RelayAccessPoint [peerAddr])
-> m ([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map RelayAccessPoint [peerAddr]))
-> STM
m
([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map RelayAccessPoint [peerAddr])
-> m ([(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))],
Map RelayAccessPoint [peerAddr])
forall a b. (a -> b) -> a -> b
$ do
dnsDomainMap <- StrictTVar m (Map RelayAccessPoint [peerAddr])
-> STM m (Map RelayAccessPoint [peerAddr])
forall (m :: * -> *) a. MonadSTM m => StrictTVar m a -> STM m a
readTVar StrictTVar m (Map RelayAccessPoint [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 =
RelayAccessPoint
-> [peerAddr]
-> Map RelayAccessPoint [peerAddr]
-> Map RelayAccessPoint [peerAddr]
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert RelayAccessPoint
domain [peerAddr]
results' Map RelayAccessPoint [peerAddr]
dnsDomainMap
when (results' /= dnsDomainMap Map.! domain) $
writeTVar dnsDomainMapVar newDNSDomainMap
staticRootPeersGroups <- readLocalRootPeers
oldRootPeersGroups <- readTVar rootPeersGroupVar
let newRootPeersGroups =
Map RelayAccessPoint [peerAddr]
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> [(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))]
getLocalRootPeersGroups Map RelayAccessPoint [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 RelayAccessPoint [peerAddr]
-> [( HotValency
, WarmValency
, Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> [( HotValency
, WarmValency
, Map peerAddr (LocalRootConfig extraFlags))]
getLocalRootPeersGroups :: Map RelayAccessPoint [peerAddr]
-> [(HotValency, WarmValency,
Map RelayAccessPoint (LocalRootConfig extraFlags))]
-> [(HotValency, WarmValency,
Map peerAddr (LocalRootConfig extraFlags))]
getLocalRootPeersGroups Map RelayAccessPoint [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
RelayAccessPoint
dap ->
let newEntries :: Map peerAddr (LocalRootConfig extraFlags)
newEntries =
Map peerAddr (LocalRootConfig extraFlags)
-> ([peerAddr] -> Map peerAddr (LocalRootConfig extraFlags))
-> Maybe [peerAddr]
-> 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 ([(peerAddr, LocalRootConfig extraFlags)]
-> Map peerAddr (LocalRootConfig extraFlags))
-> ([peerAddr] -> [(peerAddr, LocalRootConfig extraFlags)])
-> [peerAddr]
-> Map peerAddr (LocalRootConfig extraFlags)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (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))
(Maybe [peerAddr] -> Map peerAddr (LocalRootConfig extraFlags))
-> Maybe [peerAddr] -> Map peerAddr (LocalRootConfig extraFlags)
forall a b. (a -> b) -> a -> b
$ RelayAccessPoint
-> Map RelayAccessPoint [peerAddr] -> Maybe [peerAddr]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup RelayAccessPoint
dap Map RelayAccessPoint [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 [] = DiffTime -> DNSError -> DiffTime
ttlForDnsError DiffTime
0 DNSError
DNS.NameError
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 :: DiffTime -> DNS.DNSError -> DiffTime
ttlForDnsError :: DiffTime -> DNSError -> DiffTime
ttlForDnsError DiffTime
_ DNSError
DNS.NameError = DiffTime
10800
ttlForDnsError DiffTime
ttl DNSError
_ = 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)