22
33module Cardano.DbSync.Ledger.Async where
44
5+ import Cardano.DbSync.Era.Shelley.Generic.Rewards as Generic
6+ import Cardano.DbSync.Ledger.Event
57import Cardano.DbSync.Ledger.Types
6- import Cardano.Ledger.BaseTypes (EpochNo )
8+ import Cardano.DbSync.Types
9+ import Cardano.Ledger.BaseTypes
710import Cardano.Ledger.Crypto (StandardCrypto )
811import qualified Cardano.Ledger.EpochBoundary as Ledger
12+ import qualified Cardano.Ledger.Rewards as Ledger
13+ import Cardano.Ledger.Shelley.RewardUpdate as Ledger
914import Control.Concurrent.Class.MonadSTM.Strict
1015import qualified Control.Concurrent.STM.TBQueue as TBQ
16+ import Control.Monad.Extra (whenJust )
17+ import Data.Map (Map )
18+ import Data.Set (Set )
19+ import Data.Word (Word64 )
20+
21+ --------------------------------------------------------------------------------
22+ -- EpochStake
23+ --------------------------------------------------------------------------------
1124
1225newEpochStakeChannels :: IO EpochStakeChannels
1326newEpochStakeChannels =
@@ -18,9 +31,9 @@ newEpochStakeChannels =
1831 <*> newTVarIO Nothing
1932
2033-- To be used by the main thread
21- ensureEpochDone :: EpochStakeChannels -> EpochNo -> Ledger. SnapShot StandardCrypto -> IO ()
22- ensureEpochDone sQueue epoch snapshot = atomically $ do
23- mLastEpochDone <- waitFinished sQueue
34+ ensureStakeDone :: EpochStakeChannels -> EpochNo -> Ledger. SnapShot StandardCrypto -> IO ()
35+ ensureStakeDone sQueue epoch snapshot = atomically $ do
36+ mLastEpochDone <- waitStakeFinished sQueue
2437 case mLastEpochDone of
2538 Just lastEpochDone | lastEpochDone == epoch -> pure ()
2639 _ -> do
@@ -29,8 +42,8 @@ ensureEpochDone sQueue epoch snapshot = atomically $ do
2942 retry
3043
3144-- To be used by the main thread
32- waitFinished :: EpochStakeChannels -> STM IO (Maybe EpochNo )
33- waitFinished sQueue = do
45+ waitStakeFinished :: EpochStakeChannels -> STM IO (Maybe EpochNo )
46+ waitStakeFinished sQueue = do
3447 stakeThreadState <- readTVar (epochResult sQueue)
3548 case stakeThreadState of
3649 Just (lastEpoch, Done ) -> pure $ Just lastEpoch -- Normal case
@@ -42,3 +55,74 @@ writeEpochStakeAction :: EpochStakeChannels -> EpochNo -> Ledger.SnapShot Standa
4255writeEpochStakeAction sQueue epoch snapShot checkFirst = do
4356 TBQ. writeTBQueue (estakeQueue sQueue) $ EpochStakeDBAction epoch snapShot checkFirst
4457 writeTVar (epochResult sQueue) $ Just (epoch, Running )
58+
59+ --------------------------------------------------------------------------------
60+ -- Rewards
61+ --------------------------------------------------------------------------------
62+
63+ newRewardsChannels :: IO RewardsChannels
64+ newRewardsChannels =
65+ RewardsChannels
66+ <$> TBQ. newTBQueueIO 5
67+ <*> newTVarIO Nothing
68+
69+ -- TODO: add a boolean flag that shows the start of the epoch, so that 'isNewEpoch' is more reliable
70+ asyncWriteRewards :: HasLedgerEnv -> CardanoLedgerState -> EpochNo -> Bool -> [LedgerEvent ] -> IO ()
71+ asyncWriteRewards env newState currentEpochNo isNewEpoch rewardEventsEB = do
72+ rewState <- atomically $ readTVar $ rewardsResult rc
73+ if isNewEpoch
74+ then do
75+ case rewState of
76+ Just (e', RewRunning ) | e' == currentEpochNo -> do
77+ waitRewardUntil rc (e', RewDone )
78+ _ -> do
79+ ensureRewardsDone rc currentEpochNo (findTotal rewardEventsEB)
80+ waitEBRewardsAction rc currentEpochNo rewardEventsEB
81+ else do
82+ case rewState of {}
83+ whenJust (Generic. getRewardsUpdate (getTopLevelconfigHasLedger env) (clsState newState)) $ \ ru -> do
84+ atomically $ writeRewardsAction rc currentEpochNo currentEpochNo False (Ledger. rs ru) -- (e-1) (e+1)
85+ where
86+ rc = leRewardsChans env
87+
88+ _subFromCurrentEpoch :: Word64 -> EpochNo
89+ _subFromCurrentEpoch m =
90+ if unEpochNo currentEpochNo >= m
91+ then EpochNo $ unEpochNo currentEpochNo - m
92+ else EpochNo 0
93+
94+ findTotal :: [LedgerEvent ] -> Maybe (Map StakeCred (Set (Ledger. Reward StandardCrypto )))
95+ findTotal [] = Nothing
96+ findTotal (LedgerTotalRewards _ mp : _) = Just mp
97+ findTotal (_ : rest) = findTotal rest
98+
99+ -- To be used by the main thread
100+ ensureRewardsDone :: RewardsChannels -> EpochNo -> Maybe (Map StakeCred (Set (Ledger. Reward StandardCrypto ))) -> IO ()
101+ ensureRewardsDone rc epoch mmp = do
102+ whenJust mmp $ \ mp -> do
103+ atomically $ writeRewardsAction rc epoch epoch True mp -- e-2 e-1
104+ waitRewardUntil rc (epoch, RewDone )
105+
106+ waitEBRewardsAction :: RewardsChannels -> EpochNo -> [LedgerEvent ] -> IO ()
107+ waitEBRewardsAction rc epoch les = do
108+ atomically $ do
109+ TBQ. writeTBQueue (rQueue rc) $ RewardsEpochBoundary epoch les
110+ writeTVar (rewardsResult rc) $ Just (epoch, RewEBRunning )
111+ waitRewardUntil rc (epoch, RewEBDone )
112+
113+ -- To be used by the main thread
114+ writeRewardsAction :: RewardsChannels -> EpochNo -> EpochNo -> Bool -> Map StakeCred (Set (Ledger. Reward StandardCrypto )) -> STM IO ()
115+ writeRewardsAction rc epoch epoch' checkFirst mp = do
116+ TBQ. writeTBQueue (rQueue rc) $ RewardsDBAction epoch epoch' mp checkFirst
117+ writeTVar (rewardsResult rc) $ Just (epoch, RewRunning )
118+
119+ waitRewardUntil :: RewardsChannels -> (EpochNo , EpochRewardState ) -> IO ()
120+ waitRewardUntil rc st = waitRewardUntilPred rc (== st)
121+
122+ -- blocks until the reward result satisfies a specific predicate.
123+ waitRewardUntilPred :: RewardsChannels -> ((EpochNo , EpochRewardState ) -> Bool ) -> IO ()
124+ waitRewardUntilPred rc prd = atomically $ do
125+ rewardsThreadState <- readTVar (rewardsResult rc)
126+ case rewardsThreadState of
127+ Just st | prd st -> pure ()
128+ _ -> retry
0 commit comments