shrub/pkg/hs-urbit/lib/Vere/Pier.hs
2019-06-18 15:38:24 -07:00

94 lines
2.7 KiB
Haskell

module Vere.Pier where
import ClassyPrelude
import Data.Noun
import Data.Noun.Pill
import Vere
import Vere.Pier.Types
import qualified Vere.Log as Log
import qualified Vere.Worker as Worker
ioDrivers = [] :: [IODriver]
-- This is called to make a freshly booted pier. It assigns an identity to an
-- event log and takes a chill pill.
newPier :: Pill -> FilePath -> LogIdentity -> IO Pier
newPier pill top id = do
let logPath = top <> "/log"
computeQueue <- newTQueueIO
persistQueue <- newTQueueIO
releaseQueue <- newTQueueIO
-- What we really want to do is write the log identity and then do normal
-- startup, but writeLogIdentity requires a full log state including
-- input/output queues.
logState <- Log.init logPath persistQueue (writeTQueue releaseQueue)
-- In first boot, we need to write this!
Log.writeLogIdentity logState id
let logLatestEventNumber = 0
let getEvents = Log.readEvents logState
workerState <- Worker.startWorkerProcess
Worker.bootWorker workerState id pill
performCommonPierStartup workerState computeQueue persistQueue releaseQueue logState
-- This reads in a pier
runPierFromDisk :: FilePath -> IO Pier
runPierFromDisk top = do
let logPath = top <> "/log"
computeQueue <- newTQueueIO
persistQueue <- newTQueueIO
releaseQueue <- newTQueueIO
-- What we really want to do is write the log identity and then do normal
-- startup, but writeLogIdentity requires a full log state including
-- input/output queues.
logState <- Log.init logPath persistQueue (writeTQueue releaseQueue)
-- In first boot, we need to write this!
id <- Log.readLogIdentity logState
logLatestEventNumber <- Log.latestEventNumber logState
let getEvents = Log.readEvents logState
workerState <- Worker.startWorkerProcess
Worker.resumeWorker workerState id logLatestEventNumber getEvents
performCommonPierStartup workerState computeQueue persistQueue releaseQueue logState
performCommonPierStartup :: Worker.Worker
-> TQueue Noun
-> TQueue (Writ [Eff])
-> TQueue (Writ [Eff])
-> LogState
-> IO Pier
performCommonPierStartup workerState computeQueue persistQueue releaseQueue logState = do
for ioDrivers $ \x -> do
bootMessage <- bornEvent x
atomically $ writeTQueue computeQueue bootMessage
driverThreads <- for ioDrivers $ \x -> do
startDriver x (writeTQueue computeQueue)
-- TODO: Don't do a bunch of extra work; we send all events to all drivers
portingThread <- async $ do
forever $ do
r <- atomically (readTQueue releaseQueue)
for_ driverThreads $ \(_, k) ->
for_ (payload r) $ \eff ->
k eff
Worker.workerThread workerState
pure (Pier{..})