cqrs-example-0.10.0: src/CQRSExample/Notifications.hs
{-# LANGUAGE OverloadedStrings #-}
module CQRSExample.Notifications
( updateNotifications
, Notifications
) where
import Data.Aeson (ToJSON(..), object, (.=))
import Data.CQRS.Query (PersistedEvent(..))
import qualified Data.Foldable as F
import Data.Monoid ((<>))
import Data.Sequence (Seq)
import qualified Data.Sequence as S
import Data.Text (Text)
import Data.UUID.Types (UUID)
import CQRSExample.Events (Event(..), TaskEvent(..))
-- The available types of individual notifications.
data Notification =
AddedTask Text
| ArchivedTask
| Refresh
deriving (Show, Eq, Ord)
-- Convert a notification to JSON
instance ToJSON Notification where
toJSON (AddedTask title) =
object [ "type" .= ("added-task" :: Text)
, "title" .= title ]
toJSON ArchivedTask =
object [ "type" .= ("archived-task" :: Text)
]
toJSON Refresh =
object [ "type" .= ("refresh" :: Text)
]
-- Notifications that have been gathered up. Forms a monoid whose
-- operator corresponds to the aggregation of notifications.
data Notifications = Notifications (Seq Notification)
deriving (Eq, Show)
instance ToJSON Notifications where
toJSON (Notifications ns) =
object [ "notifications" .= (toJSON $ F.toList ns) ]
instance Monoid Notifications where
mempty = Notifications mempty
mappend (Notifications ns) (Notifications ns') = Notifications (ns <> ns')
-- Update a Notifications value to account for the given persisted events.
-- Ideally, we'd coalesce multiple notifications of the same types, but for
-- this example it's not really necessary so we'll just keep it simple.
updateNotifications :: (UUID, [PersistedEvent Event]) -> Notifications -> Notifications
updateNotifications (_, publishedEvents) (Notifications notifications) =
Notifications $ notifications <> F.foldMap (S.fromList . f . peEvent) publishedEvents
where
f (TaskEvent (TaskAdded title)) =
[ AddedTask title, Refresh ]
f (TaskEvent TaskCompleted) =
[ Refresh ]
f (TaskEvent TaskReopened) =
[ Refresh ]
f (TaskEvent TaskArchived) =
[ ArchivedTask, Refresh ]