Skip to content

Commit 58a7501

Browse files
committed
Enhance NodeState to keep track of next EventId
This way we keep it in memory, but do not make the HeadLogic depend on or require the current / next EventId.
1 parent b06f908 commit 58a7501

File tree

3 files changed

+32
-14
lines changed

3 files changed

+32
-14
lines changed

hydra-node/src/Hydra/Node.hs

+30-12
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Control.Concurrent.Class.MonadSTM (
1515
labelTVarIO,
1616
newTVarIO,
1717
stateTVar,
18+
writeTVar,
1819
)
1920
import Control.Monad.Trans.Writer (execWriter, tell)
2021
import Hydra.API.ClientInput (ClientInput)
@@ -33,7 +34,7 @@ import Hydra.Chain.Direct.Tx (verificationKeyToOnChainId)
3334
import Hydra.Chain.Direct.Util (readFileTextEnvelopeThrow)
3435
import Hydra.Crypto (AsType (AsHydraKey))
3536
import Hydra.Environment (Environment (..))
36-
import Hydra.Events (EventSink (..), EventSource (..), StateEvent (..), putEventToSinks, putEventsToSinks, stateChanged)
37+
import Hydra.Events (EventId, EventSink (..), EventSource (..), StateEvent (..), getEventId, putEventToSinks, putEventsToSinks, stateChanged)
3738
import Hydra.HeadLogic (
3839
Effect (..),
3940
HeadState (..),
@@ -179,6 +180,7 @@ hydrate ::
179180
m (WetHydraNode tx m)
180181
hydrate eventSource eventSinks dryNode = do
181182
events <- getEvents eventSource
183+
let lastSeenEventId = getEventId . last <$> nonEmpty events
182184
traceWith tracer LoadedState{numberOfEvents = fromIntegral $ length events}
183185
let headState = recoverState initialState (stateChanged <$> events)
184186
chainStateHistory = recoverChainStateHistory initialChainState (stateChanged <$> events)
@@ -187,7 +189,7 @@ hydrate eventSource eventSinks dryNode = do
187189
-- deliver to sinks per spec, deduplication is handled by the sinks
188190
-- FIXME(Elaine): persistence currently not handling duplication, so this relies on not providing the eventSource's sink as an arg here
189191
putEventsToSinks eventSinks events
190-
nodeState <- createNodeState headState
192+
nodeState <- createNodeState lastSeenEventId headState
191193
inputQueue <- createInputQueue
192194
pure
193195
WetHydraNode
@@ -312,13 +314,17 @@ processNextInput HydraNode{nodeState, ledger, env} e =
312314

313315
computeOutcome = HeadLogic.update env ledger
314316

315-
processStateChanges :: Monad m => HydraNode tx m -> [StateChanged tx] -> m ()
317+
processStateChanges :: MonadSTM m => HydraNode tx m -> [StateChanged tx] -> m ()
316318
processStateChanges node stateChanges = do
317-
-- TODO: obviously don't do this
318-
let events = zipWith (\eventId stateChanged -> StateEvent{eventId, stateChanged}) [0 ..] stateChanges
319+
events <- atomically . forM stateChanges $ \stateChanged -> do
320+
eventId <- getNextEventId
321+
pure StateEvent{eventId, stateChanged}
319322
forM_ events $ putEventToSinks eventSinks
320323
where
321-
HydraNode{eventSinks} = node
324+
HydraNode
325+
{ eventSinks
326+
, nodeState = NodeState{getNextEventId}
327+
} = node
322328

323329
processEffects ::
324330
( MonadAsync m
@@ -358,17 +364,29 @@ processEffects node tracer inputId effects = do
358364
data NodeState tx m = NodeState
359365
{ modifyHeadState :: forall a. (HeadState tx -> (a, HeadState tx)) -> STM m a
360366
, queryHeadState :: STM m (HeadState tx)
367+
, getNextEventId :: STM m EventId
361368
}
362369

363370
-- | Initialize a new 'NodeState'.
364-
createNodeState :: MonadLabelledSTM m => HeadState tx -> m (NodeState tx m)
365-
createNodeState initialState = do
366-
tv <- newTVarIO initialState
367-
labelTVarIO tv "node-state"
371+
createNodeState ::
372+
MonadLabelledSTM m =>
373+
-- | Last seen 'EventId'.
374+
Maybe EventId ->
375+
HeadState tx ->
376+
m (NodeState tx m)
377+
createNodeState lastSeenEventId initialState = do
378+
nextEventIdV <- newTVarIO $ maybe 0 (+ 1) lastSeenEventId
379+
labelTVarIO nextEventIdV "next-event-id"
380+
hs <- newTVarIO initialState
381+
labelTVarIO hs "head-state"
368382
pure
369383
NodeState
370-
{ modifyHeadState = stateTVar tv
371-
, queryHeadState = readTVar tv
384+
{ modifyHeadState = stateTVar hs
385+
, queryHeadState = readTVar hs
386+
, getNextEventId = do
387+
eventId <- readTVar nextEventIdV
388+
writeTVar nextEventIdV $ eventId + 1
389+
pure eventId
372390
}
373391

374392
-- * Logging

hydra-node/test/Hydra/BehaviorSpec.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ withHydraNode ::
746746
withHydraNode signingKey otherParties chain action = do
747747
outputs <- atomically newTQueue
748748
outputHistory <- newTVarIO mempty
749-
nodeState <- createNodeState $ Idle IdleState{chainState = SimpleChainState{slot = ChainSlot 0}}
749+
nodeState <- createNodeState Nothing $ Idle IdleState{chainState = SimpleChainState{slot = ChainSlot 0}}
750750
node <- createHydraNode traceInIOSim simpleLedger nodeState signingKey otherParties outputs outputHistory chain testContestationPeriod
751751
withAsync (runHydraNode node) $ \_ ->
752752
action (createTestHydraClient outputs outputHistory node nodeState)

hydra-node/test/Hydra/Model.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ seedWorld seedKeys seedCP futureCommits = do
587587
labelTQueueIO outputs ("outputs-" <> shortLabel hsk)
588588
outputHistory <- newTVarIO []
589589
labelTVarIO outputHistory ("history-" <> shortLabel hsk)
590-
nodeState <- createNodeState $ HeadState.Idle IdleState{chainState = initialChainState}
590+
nodeState <- createNodeState Nothing $ HeadState.Idle IdleState{chainState = initialChainState}
591591
node <- createHydraNode (contramap Node tr) ledger nodeState hsk otherParties outputs outputHistory mockChain seedCP
592592
let testClient = createTestHydraClient outputs outputHistory node nodeState
593593
nodeThread <- async $ labelThisThread ("node-" <> shortLabel hsk) >> runHydraNode node

0 commit comments

Comments
 (0)