urbit/pkg/hs/urbit-king/lib/Urbit/Vere/Serf.hs

116 lines
3.0 KiB
Haskell
Raw Normal View History

2020-01-23 07:16:09 +03:00
{-|
2020-05-28 21:21:43 +03:00
High-Level Serf Interface
2019-07-17 02:14:46 +03:00
-}
module Urbit.Vere.Serf
( module Urbit.Vere.Serf.IPC
, withSerf
, execReplay
)
where
import Urbit.Prelude
import Data.Conduit
2020-05-28 21:21:43 +03:00
-- ort System.ProgressBar
-- ort Urbit.Arvo
import Urbit.Vere.Pier.Types
import Urbit.Vere.Serf.IPC
2020-05-28 21:21:43 +03:00
-- ort Urbit.King.App (HasStderrLogFunc(..))
import qualified Data.Conduit.Combinators as CC
2020-05-28 21:21:43 +03:00
-- ort qualified Urbit.Ob as Ob
-- ort qualified Urbit.Time as Time
import qualified Urbit.Vere.Log as Log
--------------------------------------------------------------------------------
-- TODO XXX HACK FIXME
data MissingBootEventsInEventLog = MissingBootEventsInEventLog Word Word
deriving (Show, Exception)
--------------------------------------------------------------------------------
bytesNouns :: MonadIO m => ConduitT ByteString Noun m ()
bytesNouns = await >>= \case
Nothing -> pure ()
Just bs -> do
noun <- cueBSExn bs
(mug :: Noun, bod) <- fromNounExn noun
yield bod
bytesNouns
2020-05-28 01:57:34 +03:00
withSerf :: HasLogFunc e => Config -> RAcquire e Serf
withSerf config = mkRAcquire startup kill
where
startup = do
(serf, st) <- io $ start config
logTrace (displayShow st)
pure serf
2020-05-28 01:57:34 +03:00
kill serf = do
void $ rio $ shutdown serf
execReplay
:: forall e
. HasLogFunc e
=> Serf
-> Log.EventLog
-> Maybe Word64
-> RIO e (Maybe PlayBail)
execReplay serf log last = do
2020-05-28 01:57:34 +03:00
lastEventInSnap <- io (serfLastEventBlocking serf)
if lastEventInSnap == 0 then doBoot else doReplay
where
doBoot :: RIO e (Maybe PlayBail)
doBoot = do
2020-05-28 01:57:34 +03:00
logTrace "Beginning boot sequence"
let bootSeqLen = lifecycleLen (Log.identity log)
evs <- runConduit $ Log.streamEvents log 1
.| CC.take (fromIntegral bootSeqLen)
.| bytesNouns
.| CC.sinkList
let numEvs = fromIntegral (length evs)
2020-05-28 01:57:34 +03:00
when (numEvs /= bootSeqLen) $ do
throwIO (MissingBootEventsInEventLog numEvs bootSeqLen)
io (bootSeq serf evs) >>= \case
Just err -> pure (Just err)
Nothing -> doReplay
doReplay :: RIO e (Maybe PlayBail)
doReplay = do
2020-02-06 02:20:32 +03:00
logTrace "Beginning event log replay"
2020-05-28 01:57:34 +03:00
lastEventInSnap <- io (serfLastEventBlocking serf)
2020-02-06 02:20:32 +03:00
last & \case
Nothing -> pure ()
Just lt -> logTrace $ display $
"User requested to replay up to event #" <> tshow lt
logLastEv :: Word64 <- fromIntegral <$> Log.lastEv log
logTrace $ display $ "Last event in event log is #" <> tshow logLastEv
let replayUpTo = min (fromMaybe logLastEv last) logLastEv
2020-02-06 02:20:32 +03:00
let numEvs :: Int = fromIntegral replayUpTo - fromIntegral lastEventInSnap
when (numEvs < 0) $ do
error "impossible"
2020-02-06 02:20:32 +03:00
logTrace $ display $ "Replaying up to event #" <> tshow replayUpTo
logTrace $ display $ "Will replay " <> tshow numEvs <> " in total."
runConduit $ Log.streamEvents log (lastEventInSnap + 1)
2020-02-06 02:20:32 +03:00
.| CC.take (fromIntegral numEvs)
.| bytesNouns
.| replay 10 serf