packages feed

cqrs-example-0.9.0: src/CQRSExample/Main.hs

import           Control.Concurrent (forkIO)
import           Control.Concurrent.STM (atomically, TChan)
import qualified Control.Concurrent.STM.TChan as C
import           Control.Concurrent.STM.TVar (TVar, newTVarIO)
import           Control.Monad (void, forM_)
import           Control.Monad.Trans.Class (lift)
import           Data.Conduit (runResourceT, ($$), awaitForever)
import           Data.CQRS.EventStore.Backend.Memory (createBackendPool)
import           Data.CQRS.Query (EventStoreBackend, Repository, enumerateAndStreamEvents)
import           Data.CQRS.Repository (Settings(..))
import qualified Data.CQRS.Repository as R
import           Network.Wai.EventSource (ServerEvent(..))
import           Web.Scotty (scotty)

import           CQRSExample.Events
import           CQRSExample.Instances ()
import           CQRSExample.Notifications
import           CQRSExample.Query
import           CQRSExample.Routing

-- Source of refresh events to the browser.
eventSourcingThread :: EventStoreBackend b => TVar QueryState -> TChan ServerEvent -> Repository Event b -> IO ()
eventSourcingThread qs serverEvents repository = do
  putStrLn "Sourcing events..."
  -- Sink for sourced events
  runResourceT $ (enumerateAndStreamEvents repository) $$ sink
  where
    sink = awaitForever $ \events -> lift $ lift $ do
      forM_ events $ runQuery qs . reactToEvent
      atomically . C.writeTChan serverEvents . toServerEvent $ calculateNotifications events


-- Start serving the application.
startServing :: IO ()
startServing = do
  qState <- newTVarIO newQueryState

  -- Queue of json events to send to browser.
  serverEvents <- atomically $ C.newBroadcastTChan

  -- Create the repository.
  repository <- do
    let repositorySettings = R.defaultSettings {
                                 settingsSnapshotFrequency = Just 10 }
    pool <- createBackendPool 5
    R.newRepository repositorySettings pool

  -- Start sourcing events.
  void $ forkIO $ do
    eventSourcingThread qState serverEvents repository

  -- Web serving thread.
  void $ forkIO $ do
    scotty 8000 $ routes qState repository serverEvents


main :: IO ()
main = do
  putStrLn "Starting..."
  startServing
  putStrLn "Press <Enter> to quit"
  _ <- getLine
  return ()