<commit_before>{-# LANGUAGE AllowAmbiguousTypes #-}

-- | Workers responsible for Leaders and Richmen computation.

module Pos.Lrc.Worker
       ( LrcModeFullNoSemaphore
       , LrcModeFull
       , lrcOnNewSlotWorker
       , lrcSingleShot
       , lrcSingleShotNoLock
       ) where

import           Universum

import           Control.Lens               (views)
import           Control.Monad.Catch        (bracketOnError)
import           Control.Monad.STM          (retry)
import           Data.Conduit               (runConduitRes, (.|))
import qualified Data.HashMap.Strict        as HM
import qualified Data.HashSet               as HS
import           Ether.Internal             (HasLens (..))
import           Formatting                 (build, sformat, (%))
import           Mockable                   (forConcurrently)
import           Serokell.Util.Exceptions   ()
import           System.Wlog                (logDebug, logInfo, logWarning)

import           Pos.Binary.Communication   ()
import           Pos.Block.Logic.Internal   (BypassSecurityCheck (..), MonadBlockApply,
                                             applyBlocksUnsafe, rollbackBlocksUnsafe)
import           Pos.Communication.Protocol (OutSpecs, WorkerSpec, localOnNewSlotWorker)
import           Pos.Context                (recoveryCommGuard)
import           Pos.Core                   (Coin, EpochIndex, EpochOrSlot (..),
                                             EpochOrSlot (..), SharedSeed, SlotId (..),
                                             StakeholderId, crucialSlot, epochIndexL,
                                             getEpochOrSlot, getSlotIndex,
                                             slotSecurityParam)
import qualified Pos.DB.DB                  as DB
import qualified Pos.GState                 as GS
import           Pos.Infra.Semaphore        (BlkSemaphore, withBlkSemaphore)
import           Pos.Lrc.Consumer           (LrcConsumer (..))
import           Pos.Lrc.Consumers          (allLrcConsumers)
import           Pos.Lrc.Context            (LrcContext (lcLrcSync), LrcSyncData (..))
import           Pos.Lrc.DB                 (IssuersStakes, getLeaders, getSeed, putEpoch,
                                             putIssuersStakes, putLeaders, putSeed)
import           Pos.Lrc.Error              (LrcError (..))
import           Pos.Lrc.Fts                (followTheSatoshiM)
import           Pos.Lrc.Logic              (findAllRichmenMaybe)
import           Pos.Lrc.Mode               (LrcMode)
import           Pos.Reporting              (reportError)
import           Pos.Slotting               (MonadSlots)
import           Pos.Ssc.Class              (SscHelpersClass, SscWorkersClass)
import           Pos.Ssc.Extra              (MonadSscMem, sscCalculateSeed)
import           Pos.Update.DB              (getCompetingBVStates)
import           Pos.Update.Poll.Types      (BlockVersionState (..))
import           Pos.Util                   (logWarningWaitLinear, maybeThrow)
import           Pos.Util.Chrono            (NewestFirst (..), toOldestFirst)
import           Pos.WorkMode.Class         (WorkMode)

lrcOnNewSlotWorker
    :: forall ssc ctx m.
       (WorkMode ssc ctx m, SscWorkersClass ssc)
    => (WorkerSpec m, OutSpecs)
lrcOnNewSlotWorker = localOnNewSlotWorker True $ \SlotId {..} ->
    recoveryCommGuard $
        when (getSlotIndex siSlot < fromIntegral slotSecurityParam) $
            lrcSingleShot @ssc @ctx siEpoch `catch` onLrcError
  where
    -- Here we log it as a warning and report an error, even though it
    -- can happen there we don't know recent blocks. That's because if
    -- we don't know them, we should be in recovery mode and this
    -- worker should be turned off.
    onLrcError e@UnknownBlocksForLrc = reportE e -- FIX why we don't throw here?
    onLrcError e                     = reportE e >> throwM e

    -- REPORT:ERROR LRC worker failed with some LRC-related error
    reportE e = reportError $
        "Lrc worker failed with error: " <> show e

type LrcModeFullNoSemaphore ssc ctx m =
    ( LrcMode ssc ctx m
    , SscWorkersClass ssc
    , SscHelpersClass ssc<commit_msg>[CSL-1340] Resolve a FIXME<commit_after>{-# LANGUAGE AllowAmbiguousTypes #-}

-- | Workers responsible for Leaders and Richmen computation.

module Pos.Lrc.Worker
       ( LrcModeFullNoSemaphore
       , LrcModeFull
       , lrcOnNewSlotWorker
       , lrcSingleShot
       , lrcSingleShotNoLock
       ) where

import           Universum

import           Control.Lens               (views)
import           Control.Monad.Catch        (bracketOnError)
import           Control.Monad.STM          (retry)
import           Data.Conduit               (runConduitRes, (.|))
import qualified Data.HashMap.Strict        as HM
import qualified Data.HashSet               as HS
import           Ether.Internal             (HasLens (..))
import           Formatting                 (build, sformat, (%))
import           Mockable                   (forConcurrently)
import           Serokell.Util.Exceptions   ()
import           System.Wlog                (logDebug, logInfo, logWarning)

import           Pos.Binary.Communication   ()
import           Pos.Block.Logic.Internal   (BypassSecurityCheck (..), MonadBlockApply,
                                             applyBlocksUnsafe, rollbackBlocksUnsafe)
import           Pos.Communication.Protocol (OutSpecs, WorkerSpec, localOnNewSlotWorker)
import           Pos.Context                (recoveryCommGuard)
import           Pos.Core                   (Coin, EpochIndex, EpochOrSlot (..),
                                             EpochOrSlot (..), SharedSeed, SlotId (..),
                                             StakeholderId, crucialSlot, epochIndexL,
                                             getEpochOrSlot, getSlotIndex,
                                             slotSecurityParam)
import qualified Pos.DB.DB                  as DB
import qualified Pos.GState                 as GS
import           Pos.Infra.Semaphore        (BlkSemaphore, withBlkSemaphore)
import           Pos.Lrc.Consumer           (LrcConsumer (..))
import           Pos.Lrc.Consumers          (allLrcConsumers)
import           Pos.Lrc.Context            (LrcContext (lcLrcSync), LrcSyncData (..))
import           Pos.Lrc.DB                 (IssuersStakes, getLeaders, getSeed, putEpoch,
                                             putIssuersStakes, putLeaders, putSeed)
import           Pos.Lrc.Error              (LrcError (..))
import           Pos.Lrc.Fts                (followTheSatoshiM)
import           Pos.Lrc.Logic              (findAllRichmenMaybe)
import           Pos.Lrc.Mode               (LrcMode)
import           Pos.Reporting              (reportError)
import           Pos.Slotting               (MonadSlots)
import           Pos.Ssc.Class              (SscHelpersClass, SscWorkersClass)
import           Pos.Ssc.Extra              (MonadSscMem, sscCalculateSeed)
import           Pos.Update.DB              (getCompetingBVStates)
import           Pos.Update.Poll.Types      (BlockVersionState (..))
import           Pos.Util                   (logWarningWaitLinear, maybeThrow)
import           Pos.Util.Chrono            (NewestFirst (..), toOldestFirst)
import           Pos.WorkMode.Class         (WorkMode)

lrcOnNewSlotWorker
    :: forall ssc ctx m.
       (WorkMode ssc ctx m, SscWorkersClass ssc)
    => (WorkerSpec m, OutSpecs)
lrcOnNewSlotWorker = localOnNewSlotWorker True $ \SlotId {..} ->
    recoveryCommGuard $
        when (getSlotIndex siSlot < fromIntegral slotSecurityParam) $
            lrcSingleShot @ssc @ctx siEpoch `catch` onLrcError
  where
    -- Here we log it as a warning and report an error, even though it
    -- can happen there we don't know recent blocks. That's because if
    -- we don't know them, we should be in recovery mode and this
    -- worker should be turned off.
    --
    -- We don't rethrow it though, because probably it can happen in
    -- some corner cases but it doesn't indicate an error (maybe only
    -- 'recoveryCommGuard' error).
    onLrcError e@UnknownBlocksForLrc = reportE e
    onLrcError e                     = reportE e >> throwM e

    -- REPORT:ERROR LRC worker failed with some LRC-related error
    reportE e = reportError $
        "Lrc worker failed with error: " <> show e

type LrcModeFullNoSemaphore ssc ctx m =
    ( LrcMode ssc ctx m
    , SscWorkersClass ssc
    , SscHelpersClass ssc
{'fraction_non_alphanumeric': 0.07094117647058823, 'fraction_numerical': 0.00047058823529411766, 'mean_word_length': 1.5878234398782345, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7027907', 'n_tokens_mistral': 2304, 'n_tokens_neox': 2252, 'n_words': 592}