{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE NamedFieldPuns      #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Ouroboros.Network.PeerSelection.Governor.BigLedgerPeers
  ( belowTarget
  , aboveTarget
  ) where

import Data.Map.Strict qualified as Map
import Data.Set (Set)
import Data.Set qualified as Set
import GHC.Stack (HasCallStack)

import Control.Applicative (Alternative)
import Control.Concurrent.JobPool (Job (..))
import Control.Exception (SomeException)
import Control.Monad.Class.MonadSTM
import Control.Monad.Class.MonadTime.SI

import Ouroboros.Network.PeerSelection.Bootstrap (requiresBootstrapPeers)
import Ouroboros.Network.PeerSelection.Governor.Types
import Ouroboros.Network.PeerSelection.LedgerPeers (LedgerPeersKind (..))
import Ouroboros.Network.PeerSelection.PeerAdvertise (PeerAdvertise (..))
import Ouroboros.Network.PeerSelection.PublicRootPeers (PublicRootPeers)
import Ouroboros.Network.PeerSelection.PublicRootPeers qualified as PublicRootPeers
import Ouroboros.Network.PeerSelection.State.KnownPeers qualified as KnownPeers
import Ouroboros.Network.PeerSelection.State.LocalRootPeers qualified as LocalRootPeers


belowTarget :: (MonadSTM m, Ord peeraddr)
            => PeerSelectionActions peeraddr peerconn m
            -> Time
            -> PeerSelectionState peeraddr peerconn
            -> Guarded (STM m) (TimedDecision m peeraddr peerconn)
belowTarget :: forall (m :: * -> *) peeraddr peerconn.
(MonadSTM m, Ord peeraddr) =>
PeerSelectionActions peeraddr peerconn m
-> Time
-> PeerSelectionState peeraddr peerconn
-> Guarded (STM m) (TimedDecision m peeraddr peerconn)
belowTarget PeerSelectionActions peeraddr peerconn m
actions
            Time
blockedAt
            st :: PeerSelectionState peeraddr peerconn
st@PeerSelectionState {
              Time
bigLedgerPeerRetryTime :: Time
bigLedgerPeerRetryTime :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> Time
bigLedgerPeerRetryTime,
              Bool
inProgressBigLedgerPeersReq :: Bool
inProgressBigLedgerPeersReq :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> Bool
inProgressBigLedgerPeersReq,
              targets :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> PeerSelectionTargets
targets = PeerSelectionTargets {
                          Int
targetNumberOfKnownBigLedgerPeers :: Int
targetNumberOfKnownBigLedgerPeers :: PeerSelectionTargets -> Int
targetNumberOfKnownBigLedgerPeers
                        },
              LedgerStateJudgement
ledgerStateJudgement :: LedgerStateJudgement
ledgerStateJudgement :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> LedgerStateJudgement
ledgerStateJudgement,
              UseBootstrapPeers
bootstrapPeersFlag :: UseBootstrapPeers
bootstrapPeersFlag :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> UseBootstrapPeers
bootstrapPeersFlag
            }
      -- Are we in a sensitive state? We shouldn't attempt to fetch ledger peers
      -- in a sensitive state since we only want to connect to trustable peers.
    | Bool -> Bool
not (UseBootstrapPeers -> LedgerStateJudgement -> Bool
requiresBootstrapPeers UseBootstrapPeers
bootstrapPeersFlag LedgerStateJudgement
ledgerStateJudgement)

      -- Do we need more big ledger peers?
    , Int
maxExtraBigLedgerPeers Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0

    , Bool -> Bool
not Bool
inProgressBigLedgerPeersReq

    , Time
blockedAt Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
>= Time
bigLedgerPeerRetryTime
    = Maybe Time
-> STM m (TimedDecision m peeraddr peerconn)
-> Guarded (STM m) (TimedDecision m peeraddr peerconn)
forall (m :: * -> *) a. Maybe Time -> m a -> Guarded m a
Guarded Maybe Time
forall a. Maybe a
Nothing (STM m (TimedDecision m peeraddr peerconn)
 -> Guarded (STM m) (TimedDecision m peeraddr peerconn))
-> STM m (TimedDecision m peeraddr peerconn)
-> Guarded (STM m) (TimedDecision m peeraddr peerconn)
forall a b. (a -> b) -> a -> b
$
        TimedDecision m peeraddr peerconn
-> STM m (TimedDecision m peeraddr peerconn)
forall a. a -> STM m a
forall (m :: * -> *) a. Monad m => a -> m a
return (TimedDecision m peeraddr peerconn
 -> STM m (TimedDecision m peeraddr peerconn))
-> TimedDecision m peeraddr peerconn
-> STM m (TimedDecision m peeraddr peerconn)
forall a b. (a -> b) -> a -> b
$ \Time
_now -> Decision {
          decisionTrace :: [TracePeerSelection peeraddr]
decisionTrace = [Int -> Int -> TracePeerSelection peeraddr
forall peeraddr. Int -> Int -> TracePeerSelection peeraddr
TraceBigLedgerPeersRequest
                             Int
targetNumberOfKnownBigLedgerPeers
                             Int
numBigLedgerPeers],
          decisionState :: PeerSelectionState peeraddr peerconn
decisionState = PeerSelectionState peeraddr peerconn
st { inProgressBigLedgerPeersReq = True },
          decisionJobs :: [Job () m (Completion m peeraddr peerconn)]
decisionJobs  = [PeerSelectionActions peeraddr peerconn m
-> Int -> Job () m (Completion m peeraddr peerconn)
forall (m :: * -> *) peeraddr peerconn.
(MonadSTM m, Ord peeraddr) =>
PeerSelectionActions peeraddr peerconn m
-> Int -> Job () m (Completion m peeraddr peerconn)
jobReqBigLedgerPeers PeerSelectionActions peeraddr peerconn m
actions Int
maxExtraBigLedgerPeers]
        }

    | Bool
otherwise
    = Maybe Time -> Guarded (STM m) (TimedDecision m peeraddr peerconn)
forall (m :: * -> *) a. Maybe Time -> Guarded m a
GuardedSkip Maybe Time
forall a. Maybe a
Nothing
  where
    PeerSelectionCounters {
        numberOfKnownBigLedgerPeers :: PeerSelectionCounters -> Int
numberOfKnownBigLedgerPeers = Int
numBigLedgerPeers
      }
      =
      PeerSelectionState peeraddr peerconn -> PeerSelectionCounters
forall peeraddr peerconn.
Ord peeraddr =>
PeerSelectionState peeraddr peerconn -> PeerSelectionCounters
peerSelectionStateToCounters PeerSelectionState peeraddr peerconn
st

    maxExtraBigLedgerPeers :: Int
maxExtraBigLedgerPeers = Int
targetNumberOfKnownBigLedgerPeers
                           Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
numBigLedgerPeers


jobReqBigLedgerPeers :: forall m peeraddr peerconn.
                        (MonadSTM m, Ord peeraddr)
                     => PeerSelectionActions peeraddr peerconn m
                     -> Int
                     -> Job () m (Completion m peeraddr peerconn)
jobReqBigLedgerPeers :: forall (m :: * -> *) peeraddr peerconn.
(MonadSTM m, Ord peeraddr) =>
PeerSelectionActions peeraddr peerconn m
-> Int -> Job () m (Completion m peeraddr peerconn)
jobReqBigLedgerPeers PeerSelectionActions{ LedgerPeersKind -> Int -> m (PublicRootPeers peeraddr, DiffTime)
requestPublicRootPeers :: LedgerPeersKind -> Int -> m (PublicRootPeers peeraddr, DiffTime)
requestPublicRootPeers :: forall peeraddr peerconn (m :: * -> *).
PeerSelectionActions peeraddr peerconn m
-> LedgerPeersKind -> Int -> m (PublicRootPeers peeraddr, DiffTime)
requestPublicRootPeers }
                     Int
numExtraAllowed =
    m (Completion m peeraddr peerconn)
-> (SomeException -> m (Completion m peeraddr peerconn))
-> ()
-> String
-> Job () m (Completion m peeraddr peerconn)
forall group (m :: * -> *) a.
m a -> (SomeException -> m a) -> group -> String -> Job group m a
Job m (Completion m peeraddr peerconn)
job (Completion m peeraddr peerconn
-> m (Completion m peeraddr peerconn)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Completion m peeraddr peerconn
 -> m (Completion m peeraddr peerconn))
-> (SomeException -> Completion m peeraddr peerconn)
-> SomeException
-> m (Completion m peeraddr peerconn)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> Completion m peeraddr peerconn
handler) () String
"reqBigLedgerPeers"
  where
    handler :: SomeException -> Completion m peeraddr peerconn
    handler :: SomeException -> Completion m peeraddr peerconn
handler SomeException
e =
      (PeerSelectionState peeraddr peerconn
 -> Time -> Decision m peeraddr peerconn)
-> Completion m peeraddr peerconn
forall (m :: * -> *) peeraddr peerconn.
(PeerSelectionState peeraddr peerconn
 -> Time -> Decision m peeraddr peerconn)
-> Completion m peeraddr peerconn
Completion ((PeerSelectionState peeraddr peerconn
  -> Time -> Decision m peeraddr peerconn)
 -> Completion m peeraddr peerconn)
-> (PeerSelectionState peeraddr peerconn
    -> Time -> Decision m peeraddr peerconn)
-> Completion m peeraddr peerconn
forall a b. (a -> b) -> a -> b
$ \PeerSelectionState peeraddr peerconn
st Time
now ->
      -- This is a failure, so move the backoff counter one in the failure
      -- direction (negative) and schedule the next retry time accordingly.
      -- We use an exponential backoff strategy. The max retry time of 2^8
      -- seconds is just over 4 minutes.
      let bigLedgerPeerBackoffs'      :: Int
          bigLedgerPeerBackoffs' :: Int
bigLedgerPeerBackoffs'      = (PeerSelectionState peeraddr peerconn -> Int
forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> Int
bigLedgerPeerBackoffs PeerSelectionState peeraddr peerconn
st Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
0) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1

          bigLedgerPeerRetryDiffTime' :: DiffTime
          bigLedgerPeerRetryDiffTime' :: DiffTime
bigLedgerPeerRetryDiffTime' = DiffTime
2 DiffTime -> Int -> DiffTime
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int -> Int
forall a. Num a => a -> a
abs Int
bigLedgerPeerBackoffs' Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
8)

          bigLedgerPeerRetryTime'     :: Time
          bigLedgerPeerRetryTime' :: Time
bigLedgerPeerRetryTime'     = DiffTime -> Time -> Time
addTime DiffTime
bigLedgerPeerRetryDiffTime' Time
now
       in Decision {
            decisionTrace :: [TracePeerSelection peeraddr]
decisionTrace = [SomeException -> Int -> DiffTime -> TracePeerSelection peeraddr
forall peeraddr.
SomeException -> Int -> DiffTime -> TracePeerSelection peeraddr
TraceBigLedgerPeersFailure
                               SomeException
e
                               Int
bigLedgerPeerBackoffs'
                               DiffTime
bigLedgerPeerRetryDiffTime'],
            decisionState :: PeerSelectionState peeraddr peerconn
decisionState = PeerSelectionState peeraddr peerconn
st {
                              inProgressBigLedgerPeersReq = False,
                              bigLedgerPeerBackoffs       = bigLedgerPeerBackoffs',
                              bigLedgerPeerRetryTime      = bigLedgerPeerRetryTime'
                            },
            decisionJobs :: [Job () m (Completion m peeraddr peerconn)]
decisionJobs  = []
          }

    job :: m (Completion m peeraddr peerconn)
    job :: m (Completion m peeraddr peerconn)
job = do
      (results, ttl) <- LedgerPeersKind -> Int -> m (PublicRootPeers peeraddr, DiffTime)
requestPublicRootPeers LedgerPeersKind
BigLedgerPeers Int
numExtraAllowed
      return $ Completion $ \PeerSelectionState peeraddr peerconn
st Time
now ->
        let -- We make sure the set of big ledger peers disjoint from the sum
            -- of local, public and ledger peers.
            newPeers :: PublicRootPeers peeraddr
            newPeers :: PublicRootPeers peeraddr
newPeers = PublicRootPeers peeraddr
results
                       PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
`PublicRootPeers.difference`
                       (   LocalRootPeers peeraddr -> Set peeraddr
forall peeraddr. LocalRootPeers peeraddr -> Set peeraddr
LocalRootPeers.keysSet (PeerSelectionState peeraddr peerconn -> LocalRootPeers peeraddr
forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> LocalRootPeers peeraddr
localRootPeers PeerSelectionState peeraddr peerconn
st)
                        Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Semigroup a => a -> a -> a
<> PublicRootPeers peeraddr -> Set peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr -> Set peeraddr
PublicRootPeers.toSet (PeerSelectionState peeraddr peerconn -> PublicRootPeers peeraddr
forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> PublicRootPeers peeraddr
publicRootPeers PeerSelectionState peeraddr peerconn
st))

            newPeersSet :: Set peeraddr
newPeersSet      = PublicRootPeers peeraddr -> Set peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr -> Set peeraddr
PublicRootPeers.toSet PublicRootPeers peeraddr
newPeers
            publicRootPeers' :: PublicRootPeers peeraddr
publicRootPeers' = PeerSelectionState peeraddr peerconn -> PublicRootPeers peeraddr
forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> PublicRootPeers peeraddr
publicRootPeers PeerSelectionState peeraddr peerconn
st PublicRootPeers peeraddr
-> PublicRootPeers peeraddr -> PublicRootPeers peeraddr
forall a. Semigroup a => a -> a -> a
<> PublicRootPeers peeraddr
newPeers

            knownPeers' :: KnownPeers peeraddr
knownPeers'
                     = Map peeraddr (Maybe PeerSharing, Maybe PeerAdvertise)
-> KnownPeers peeraddr -> KnownPeers peeraddr
forall peeraddr.
Ord peeraddr =>
Map peeraddr (Maybe PeerSharing, Maybe PeerAdvertise)
-> KnownPeers peeraddr -> KnownPeers peeraddr
KnownPeers.insert
                         ((peeraddr -> (Maybe PeerSharing, Maybe PeerAdvertise))
-> Set peeraddr
-> Map peeraddr (Maybe PeerSharing, Maybe PeerAdvertise)
forall k a. (k -> a) -> Set k -> Map k a
Map.fromSet (\peeraddr
_ -> ( Maybe PeerSharing
forall a. Maybe a
Nothing
                                               -- the peer sharing flag will be
                                               -- updated once we negotiate
                                               -- the connection
                                             , PeerAdvertise -> Maybe PeerAdvertise
forall a. a -> Maybe a
Just PeerAdvertise
DoNotAdvertisePeer
                                             ))
                                      Set peeraddr
newPeersSet)
                         (PeerSelectionState peeraddr peerconn -> KnownPeers peeraddr
forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> KnownPeers peeraddr
knownPeers PeerSelectionState peeraddr peerconn
st)

            -- We got a successful response to our request, but if we're still
            -- below target we're going to want to try again at some point.
            -- If we made progress towards our target then we will retry at the
            -- suggested ttl. But if we did not make progress then we want to
            -- follow an exponential backoff strategy. The max retry time of 2^8
            -- seconds is just over four minutes.
            bigLedgerPeerBackoffs' :: Int
            bigLedgerPeerBackoffs' :: Int
bigLedgerPeerBackoffs'
              | PublicRootPeers peeraddr -> Bool
forall peeraddr. PublicRootPeers peeraddr -> Bool
PublicRootPeers.null PublicRootPeers peeraddr
newPeers = (PeerSelectionState peeraddr peerconn -> Int
forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> Int
bigLedgerPeerBackoffs PeerSelectionState peeraddr peerconn
st Int -> Int -> Int
forall a. Ord a => a -> a -> a
`max` Int
0) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
              | Bool
otherwise = Int
0

            bigLedgerPeerRetryDiffTime :: DiffTime
            bigLedgerPeerRetryDiffTime :: DiffTime
bigLedgerPeerRetryDiffTime
              | Int
bigLedgerPeerBackoffs' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
                          = DiffTime
ttl
              | Bool
otherwise = DiffTime
2DiffTime -> Int -> DiffTime
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
bigLedgerPeerBackoffs' Int -> Int -> Int
forall a. Ord a => a -> a -> a
`min` Int
8)

            bigLedgerPeerRetryTime :: Time
            bigLedgerPeerRetryTime :: Time
bigLedgerPeerRetryTime = DiffTime
bigLedgerPeerRetryDiffTime DiffTime -> Time -> Time
`addTime` Time
now

         in Decision {
               decisionTrace :: [TracePeerSelection peeraddr]
decisionTrace = [Set peeraddr -> Int -> DiffTime -> TracePeerSelection peeraddr
forall peeraddr.
Set peeraddr -> Int -> DiffTime -> TracePeerSelection peeraddr
TraceBigLedgerPeersResults
                                 Set peeraddr
newPeersSet
                                 Int
bigLedgerPeerBackoffs'
                                 DiffTime
bigLedgerPeerRetryDiffTime],
               decisionState :: PeerSelectionState peeraddr peerconn
decisionState = PeerSelectionState peeraddr peerconn
st {
                                 publicRootPeers             = publicRootPeers',
                                 knownPeers                  = knownPeers',
                                 bigLedgerPeerBackoffs       = bigLedgerPeerBackoffs',
                                 bigLedgerPeerRetryTime      = bigLedgerPeerRetryTime,
                                 inProgressBigLedgerPeersReq = False
                               },
               decisionJobs :: [Job () m (Completion m peeraddr peerconn)]
decisionJobs  = []
             }


aboveTarget :: forall m peeraddr peerconn.
               (Alternative (STM m), MonadSTM m, Ord peeraddr, HasCallStack)
            => MkGuardedDecision peeraddr peerconn m
aboveTarget :: forall (m :: * -> *) peeraddr peerconn.
(Alternative (STM m), MonadSTM m, Ord peeraddr, HasCallStack) =>
MkGuardedDecision peeraddr peerconn m
aboveTarget PeerSelectionPolicy {PickPolicy peeraddr (STM m)
policyPickColdPeersToForget :: PickPolicy peeraddr (STM m)
policyPickColdPeersToForget :: forall peeraddr (m :: * -> *).
PeerSelectionPolicy peeraddr m -> PickPolicy peeraddr (STM m)
policyPickColdPeersToForget}
            st :: PeerSelectionState peeraddr peerconn
st@PeerSelectionState {
                 PublicRootPeers peeraddr
publicRootPeers :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> PublicRootPeers peeraddr
publicRootPeers :: PublicRootPeers peeraddr
publicRootPeers,
                 KnownPeers peeraddr
knownPeers :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> KnownPeers peeraddr
knownPeers :: KnownPeers peeraddr
knownPeers,
                 Set peeraddr
inProgressPromoteCold :: Set peeraddr
inProgressPromoteCold :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> Set peeraddr
inProgressPromoteCold,
                 targets :: forall peeraddr peerconn.
PeerSelectionState peeraddr peerconn -> PeerSelectionTargets
targets = PeerSelectionTargets {
                             Int
targetNumberOfKnownBigLedgerPeers :: PeerSelectionTargets -> Int
targetNumberOfKnownBigLedgerPeers :: Int
targetNumberOfKnownBigLedgerPeers
                           }
               }
    -- Are we above the target for number of known big ledger peers
    | Int
numKnownBigLedgerPeers Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
targetNumberOfKnownBigLedgerPeers

    -- Are there any cold big ledger peers we could pick to forget?
    , Int
numKnownBigLedgerPeers Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
numEstablishedBigLedgerPeers

    , let availableToForget :: Set peeraddr
          availableToForget :: Set peeraddr
availableToForget = Set peeraddr
bigLedgerPeersSet
                                Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
Set.\\ Set peeraddr
establishedBigLedgerPeers
                                Set peeraddr -> Set peeraddr -> Set peeraddr
forall a. Ord a => Set a -> Set a -> Set a
Set.\\ Set peeraddr
inProgressPromoteCold

    , Bool -> Bool
not (Set peeraddr -> Bool
forall a. Set a -> Bool
Set.null Set peeraddr
availableToForget)
    = Maybe Time
-> STM m (TimedDecision m peeraddr peerconn)
-> Guarded (STM m) (TimedDecision m peeraddr peerconn)
forall (m :: * -> *) a. Maybe Time -> m a -> Guarded m a
Guarded Maybe Time
forall a. Maybe a
Nothing (STM m (TimedDecision m peeraddr peerconn)
 -> Guarded (STM m) (TimedDecision m peeraddr peerconn))
-> STM m (TimedDecision m peeraddr peerconn)
-> Guarded (STM m) (TimedDecision m peeraddr peerconn)
forall a b. (a -> b) -> a -> b
$ do
        let numPeersCanForget :: Int
numPeersCanForget = Int
numKnownBigLedgerPeers
                              Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
targetNumberOfKnownBigLedgerPeers
        selectedToForget <- PeerSelectionState peeraddr peerconn
-> PickPolicy peeraddr (STM m)
-> Set peeraddr
-> Int
-> STM m (Set peeraddr)
forall peeraddr (m :: * -> *) peerconn.
(Ord peeraddr, Functor m, HasCallStack) =>
PeerSelectionState peeraddr peerconn
-> PickPolicy peeraddr m -> Set peeraddr -> Int -> m (Set peeraddr)
pickPeers PeerSelectionState peeraddr peerconn
st
                                      PickPolicy peeraddr (STM m)
policyPickColdPeersToForget
                                      Set peeraddr
availableToForget
                                      Int
numPeersCanForget
        return $ \Time
_now ->
          let knownPeers' :: KnownPeers peeraddr
knownPeers'     = Set peeraddr -> KnownPeers peeraddr -> KnownPeers peeraddr
forall peeraddr.
Ord peeraddr =>
Set peeraddr -> KnownPeers peeraddr -> KnownPeers peeraddr
KnownPeers.delete Set peeraddr
selectedToForget KnownPeers peeraddr
knownPeers
              publicRootPeers' :: PublicRootPeers peeraddr
publicRootPeers' = PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
forall peeraddr.
Ord peeraddr =>
PublicRootPeers peeraddr
-> Set peeraddr -> PublicRootPeers peeraddr
PublicRootPeers.difference PublicRootPeers peeraddr
publicRootPeers Set peeraddr
selectedToForget
          in Decision {
               decisionTrace :: [TracePeerSelection peeraddr]
decisionTrace = [Int -> Int -> Set peeraddr -> TracePeerSelection peeraddr
forall peeraddr.
Int -> Int -> Set peeraddr -> TracePeerSelection peeraddr
TraceForgetBigLedgerPeers
                                  Int
targetNumberOfKnownBigLedgerPeers
                                  Int
numKnownBigLedgerPeers
                                  Set peeraddr
selectedToForget
                               ],
               decisionState :: PeerSelectionState peeraddr peerconn
decisionState = PeerSelectionState peeraddr peerconn
st { knownPeers      = knownPeers',
                                    publicRootPeers = publicRootPeers'
                                  },
               decisionJobs :: [Job () m (Completion m peeraddr peerconn)]
decisionJobs  = []
             }

    | Bool
otherwise
    = Maybe Time -> Guarded (STM m) (TimedDecision m peeraddr peerconn)
forall (m :: * -> *) a. Maybe Time -> Guarded m a
GuardedSkip Maybe Time
forall a. Maybe a
Nothing
  where
    bigLedgerPeersSet :: Set peeraddr
bigLedgerPeersSet = PublicRootPeers peeraddr -> Set peeraddr
forall peeraddr. PublicRootPeers peeraddr -> Set peeraddr
PublicRootPeers.getBigLedgerPeers PublicRootPeers peeraddr
publicRootPeers

    PeerSelectionView {
        viewKnownBigLedgerPeers :: forall a. PeerSelectionView a -> a
viewKnownBigLedgerPeers       = (Set peeraddr
_, Int
numKnownBigLedgerPeers),
        viewEstablishedBigLedgerPeers :: forall a. PeerSelectionView a -> a
viewEstablishedBigLedgerPeers = (Set peeraddr
establishedBigLedgerPeers, Int
numEstablishedBigLedgerPeers)
      }
      =
      PeerSelectionState peeraddr peerconn
-> PeerSelectionView (Set peeraddr, Int)
forall peeraddr peerconn.
Ord peeraddr =>
PeerSelectionState peeraddr peerconn
-> PeerSelectionSetsWithSizes peeraddr
peerSelectionStateToView PeerSelectionState peeraddr peerconn
st