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
|
|
|
-}
|
|
|
|
|
2020-05-27 02:01:03 +03:00
|
|
|
module Urbit.Vere.Serf
|
|
|
|
( module Urbit.Vere.Serf.IPC
|
|
|
|
, withSerf
|
|
|
|
, execReplay
|
|
|
|
)
|
|
|
|
where
|
2019-06-01 01:55:21 +03:00
|
|
|
|
2020-01-24 08:28:38 +03:00
|
|
|
import Urbit.Prelude
|
2019-06-01 01:55:21 +03:00
|
|
|
|
2019-07-24 04:34:16 +03:00
|
|
|
import Data.Conduit
|
2020-05-28 21:21:43 +03:00
|
|
|
-- ort System.ProgressBar
|
|
|
|
-- ort Urbit.Arvo
|
2020-01-24 08:28:38 +03:00
|
|
|
import Urbit.Vere.Pier.Types
|
2020-05-27 02:01:03 +03:00
|
|
|
import Urbit.Vere.Serf.IPC
|
2020-05-28 21:21:43 +03:00
|
|
|
|
|
|
|
-- ort Urbit.King.App (HasStderrLogFunc(..))
|
|
|
|
|
2020-01-24 05:57:22 +03:00
|
|
|
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
|
2020-01-24 08:47:06 +03:00
|
|
|
import qualified Urbit.Vere.Log as Log
|
2019-06-18 02:47:20 +03:00
|
|
|
|
|
|
|
|
2019-07-19 03:52:53 +03:00
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
2020-05-27 02:01:03 +03:00
|
|
|
-- TODO XXX HACK FIXME
|
|
|
|
data MissingBootEventsInEventLog = MissingBootEventsInEventLog Word Word
|
|
|
|
deriving (Show, Exception)
|
2019-09-17 21:19:53 +03:00
|
|
|
|
2019-07-19 03:52:53 +03:00
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
2020-05-27 02:01:03 +03:00
|
|
|
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
|
2020-05-29 05:14:25 +03:00
|
|
|
withSerf config = mkRAcquire startup kill
|
2020-05-27 02:01:03 +03:00
|
|
|
where
|
2020-05-29 05:14:25 +03:00
|
|
|
startup = do
|
|
|
|
(serf, st) <- io $ start config
|
|
|
|
logTrace (displayShow st)
|
|
|
|
pure serf
|
2020-05-28 01:57:34 +03:00
|
|
|
kill serf = do
|
2020-06-01 20:51:37 +03:00
|
|
|
void $ rio $ stop serf
|
2020-05-27 02:01:03 +03:00
|
|
|
|
|
|
|
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)
|
2020-05-27 02:01:03 +03:00
|
|
|
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"
|
|
|
|
|
2020-05-27 02:01:03 +03:00
|
|
|
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)
|
2020-05-27 02:01:03 +03:00
|
|
|
|
2020-06-01 20:51:37 +03:00
|
|
|
io (boot serf evs) >>= \case
|
2020-05-27 02:01:03 +03:00
|
|
|
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-05-27 02:01:03 +03:00
|
|
|
|
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
|
|
|
|
|
2020-05-27 02:01:03 +03:00
|
|
|
let replayUpTo = min (fromMaybe logLastEv last) logLastEv
|
2020-02-06 02:20:32 +03:00
|
|
|
|
|
|
|
let numEvs :: Int = fromIntegral replayUpTo - fromIntegral lastEventInSnap
|
2020-01-11 01:07:29 +03:00
|
|
|
|
2020-05-27 02:01:03 +03:00
|
|
|
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."
|
2020-01-11 01:07:29 +03:00
|
|
|
|
2020-05-27 02:01:03 +03:00
|
|
|
runConduit $ Log.streamEvents log (lastEventInSnap + 1)
|
2020-02-06 02:20:32 +03:00
|
|
|
.| CC.take (fromIntegral numEvs)
|
2020-05-27 02:01:03 +03:00
|
|
|
.| bytesNouns
|
2020-05-29 05:14:25 +03:00
|
|
|
.| replay 10 serf
|