{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TemplateHaskell #-}

-- | Common test functionality
module Eventium.TestHelpers
  ( Counter (..),
    CounterProjection,
    counterProjection,
    CounterCommandHandler,
    counterCommandHandler,
    CounterEvent (..),
    CounterCommand (..),
    EventStoreRunner (..),
    GlobalStreamEventStoreRunner (..),
    eventStoreSpec,
    globalStreamEventStoreSpec,
    VersionedProjectionCacheRunner (..),
    versionedProjectionCacheSpec,
    GlobalStreamProjectionCacheRunner (..),
    globalStreamProjectionCacheSpec,
    Text,
    module X,
  )
where

import Control.Monad as X
import Control.Monad.IO.Class as X
import Control.Monad.Logger as X
import Data.Aeson
import Data.Aeson.Casing
import Data.Aeson.TH
import Data.Text (Text)
import Eventium
import Test.Hspec

-- | Example Projection/CommandHandler
newtype Counter = Counter {Counter -> Int
unCounter :: Int}
  deriving (Counter -> Counter -> Bool
(Counter -> Counter -> Bool)
-> (Counter -> Counter -> Bool) -> Eq Counter
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Counter -> Counter -> Bool
== :: Counter -> Counter -> Bool
$c/= :: Counter -> Counter -> Bool
/= :: Counter -> Counter -> Bool
Eq, Int -> Counter -> ShowS
[Counter] -> ShowS
Counter -> String
(Int -> Counter -> ShowS)
-> (Counter -> String) -> ([Counter] -> ShowS) -> Show Counter
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Counter -> ShowS
showsPrec :: Int -> Counter -> ShowS
$cshow :: Counter -> String
show :: Counter -> String
$cshowList :: [Counter] -> ShowS
showList :: [Counter] -> ShowS
Show, Maybe Counter
Value -> Parser [Counter]
Value -> Parser Counter
(Value -> Parser Counter)
-> (Value -> Parser [Counter]) -> Maybe Counter -> FromJSON Counter
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser Counter
parseJSON :: Value -> Parser Counter
$cparseJSONList :: Value -> Parser [Counter]
parseJSONList :: Value -> Parser [Counter]
$comittedField :: Maybe Counter
omittedField :: Maybe Counter
FromJSON, [Counter] -> Value
[Counter] -> Encoding
Counter -> Bool
Counter -> Value
Counter -> Encoding
(Counter -> Value)
-> (Counter -> Encoding)
-> ([Counter] -> Value)
-> ([Counter] -> Encoding)
-> (Counter -> Bool)
-> ToJSON Counter
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> (a -> Bool)
-> ToJSON a
$ctoJSON :: Counter -> Value
toJSON :: Counter -> Value
$ctoEncoding :: Counter -> Encoding
toEncoding :: Counter -> Encoding
$ctoJSONList :: [Counter] -> Value
toJSONList :: [Counter] -> Value
$ctoEncodingList :: [Counter] -> Encoding
toEncodingList :: [Counter] -> Encoding
$comitField :: Counter -> Bool
omitField :: Counter -> Bool
ToJSON)

data CounterEvent
  = Added
      { CounterEvent -> Int
_counterEventAmount :: Int
      }
  | CounterFailedOutOfBounds
  deriving (CounterEvent -> CounterEvent -> Bool
(CounterEvent -> CounterEvent -> Bool)
-> (CounterEvent -> CounterEvent -> Bool) -> Eq CounterEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CounterEvent -> CounterEvent -> Bool
== :: CounterEvent -> CounterEvent -> Bool
$c/= :: CounterEvent -> CounterEvent -> Bool
/= :: CounterEvent -> CounterEvent -> Bool
Eq, Int -> CounterEvent -> ShowS
[CounterEvent] -> ShowS
CounterEvent -> String
(Int -> CounterEvent -> ShowS)
-> (CounterEvent -> String)
-> ([CounterEvent] -> ShowS)
-> Show CounterEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CounterEvent -> ShowS
showsPrec :: Int -> CounterEvent -> ShowS
$cshow :: CounterEvent -> String
show :: CounterEvent -> String
$cshowList :: [CounterEvent] -> ShowS
showList :: [CounterEvent] -> ShowS
Show)

type CounterProjection = Projection Counter CounterEvent

counterProjection :: CounterProjection
counterProjection :: CounterProjection
counterProjection =
  Counter
-> (Counter -> CounterEvent -> Counter) -> CounterProjection
forall state event.
state -> (state -> event -> state) -> Projection state event
Projection
    (Int -> Counter
Counter Int
0)
    (\(Counter Int
k) (Added Int
x) -> Int -> Counter
Counter (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
x))

counterGlobalProjection :: Projection Counter (VersionedStreamEvent CounterEvent)
counterGlobalProjection :: Projection Counter (VersionedStreamEvent CounterEvent)
counterGlobalProjection =
  Counter
-> (Counter -> VersionedStreamEvent CounterEvent -> Counter)
-> Projection Counter (VersionedStreamEvent CounterEvent)
forall state event.
state -> (state -> event -> state) -> Projection state event
Projection
    (Int -> Counter
Counter Int
0)
    (\(Counter Int
k) (StreamEvent UUID
_ EventVersion
_ (Added Int
x)) -> Int -> Counter
Counter (Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
x))

data CounterCommand
  = Increment
      { CounterCommand -> Int
_counterCommandAmount :: Int
      }
  | Decrement
      { _counterCommandAmount :: Int
      }
  deriving (CounterCommand -> CounterCommand -> Bool
(CounterCommand -> CounterCommand -> Bool)
-> (CounterCommand -> CounterCommand -> Bool) -> Eq CounterCommand
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CounterCommand -> CounterCommand -> Bool
== :: CounterCommand -> CounterCommand -> Bool
$c/= :: CounterCommand -> CounterCommand -> Bool
/= :: CounterCommand -> CounterCommand -> Bool
Eq, Int -> CounterCommand -> ShowS
[CounterCommand] -> ShowS
CounterCommand -> String
(Int -> CounterCommand -> ShowS)
-> (CounterCommand -> String)
-> ([CounterCommand] -> ShowS)
-> Show CounterCommand
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CounterCommand -> ShowS
showsPrec :: Int -> CounterCommand -> ShowS
$cshow :: CounterCommand -> String
show :: CounterCommand -> String
$cshowList :: [CounterCommand] -> ShowS
showList :: [CounterCommand] -> ShowS
Show)

type CounterCommandHandler = CommandHandler Counter CounterEvent CounterCommand

counterCommandHandler :: CounterCommandHandler
counterCommandHandler :: CounterCommandHandler
counterCommandHandler = (Counter -> CounterCommand -> [CounterEvent])
-> CounterProjection -> CounterCommandHandler
forall state event command.
(state -> command -> [event])
-> Projection state event -> CommandHandler state event command
CommandHandler Counter -> CounterCommand -> [CounterEvent]
counterCommand CounterProjection
counterProjection

counterCommand :: Counter -> CounterCommand -> [CounterEvent]
counterCommand :: Counter -> CounterCommand -> [CounterEvent]
counterCommand (Counter Int
k) (Increment Int
n) =
  if Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
100
    then [Int -> CounterEvent
Added Int
n]
    else [CounterEvent
CounterFailedOutOfBounds]
counterCommand (Counter Int
k) (Decrement Int
n) =
  if Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0
    then [Int -> CounterEvent
Added (-Int
n)]
    else [CounterEvent
CounterFailedOutOfBounds]

deriveJSON (aesonPrefix camelCase) ''CounterEvent
deriveJSON (aesonPrefix camelCase) ''CounterCommand

-- Test harness for stores

newtype EventStoreRunner m
  = EventStoreRunner (forall a. (VersionedEventStoreWriter m CounterEvent -> VersionedEventStoreReader m CounterEvent -> m a) -> IO a)

eventStoreSpec ::
  (Monad m) =>
  EventStoreRunner m ->
  Spec
eventStoreSpec :: forall (m :: * -> *). Monad m => EventStoreRunner m -> Spec
eventStoreSpec (EventStoreRunner forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore) = do
  let withStoreExampleEvents :: (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStoreExampleEvents VersionedEventStoreWriter m CounterEvent
-> VersionedEventStoreReader m CounterEvent -> m a
action = (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent -> m a)
 -> IO a)
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
reader -> do
        ()
_ <- VersionedEventStoreWriter m CounterEvent -> m ()
forall (m :: * -> *).
Monad m =>
VersionedEventStoreWriter m CounterEvent -> m ()
insertExampleEvents VersionedEventStoreWriter m CounterEvent
writer
        VersionedEventStoreWriter m CounterEvent
-> VersionedEventStoreReader m CounterEvent -> m a
action VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
reader

  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when a few events are inserted" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    let sampleEvents :: [CounterEvent]
sampleEvents = [Int -> CounterEvent
Added Int
1, Int -> CounterEvent
Added Int
4, Int -> CounterEvent
Added (-Int
3), Int -> CounterEvent
Added Int
5]
        withStore' :: (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore' VersionedEventStoreWriter m CounterEvent
-> VersionedEventStoreReader m CounterEvent -> m a
action = (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent -> m a)
 -> IO a)
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
reader -> do
          Either (EventWriteError EventVersion) EventVersion
_ <- VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
NoStream [CounterEvent]
sampleEvents
          VersionedEventStoreWriter m CounterEvent
-> VersionedEventStoreReader m CounterEvent -> m a
action VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
reader

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should return events" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      [VersionedStreamEvent CounterEvent]
events' <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m [VersionedStreamEvent CounterEvent])
-> IO [VersionedStreamEvent CounterEvent]
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore' ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m [VersionedStreamEvent CounterEvent])
 -> IO [VersionedStreamEvent CounterEvent])
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m [VersionedStreamEvent CounterEvent])
-> IO [VersionedStreamEvent CounterEvent]
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader -> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> QueryRange UUID EventVersion
forall key position. key -> QueryRange key position
allEvents UUID
nil)
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events') [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [CounterEvent]
sampleEvents

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should return correct event versions" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      [VersionedStreamEvent CounterEvent]
events <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m [VersionedStreamEvent CounterEvent])
-> IO [VersionedStreamEvent CounterEvent]
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore' ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m [VersionedStreamEvent CounterEvent])
 -> IO [VersionedStreamEvent CounterEvent])
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m [VersionedStreamEvent CounterEvent])
-> IO [VersionedStreamEvent CounterEvent]
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader -> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> QueryRange UUID EventVersion
forall key position. key -> QueryRange key position
allEvents UUID
nil)
      (VersionedStreamEvent CounterEvent -> EventVersion
forall key position event.
StreamEvent key position event -> position
streamEventPosition (VersionedStreamEvent CounterEvent -> EventVersion)
-> [VersionedStreamEvent CounterEvent] -> [EventVersion]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events) [EventVersion] -> [EventVersion] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [EventVersion
0, EventVersion
1, EventVersion
2, EventVersion
3]

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should return correct events with queries" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      ([VersionedStreamEvent CounterEvent]
firstEvents, [VersionedStreamEvent CounterEvent]
middleEvents, [VersionedStreamEvent CounterEvent]
laterEvents, [VersionedStreamEvent CounterEvent]
maxEvents) <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> IO
     ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore' ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m ([VersionedStreamEvent CounterEvent],
        [VersionedStreamEvent CounterEvent],
        [VersionedStreamEvent CounterEvent],
        [VersionedStreamEvent CounterEvent]))
 -> IO
      ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
-> IO
     ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader ->
        (,,,)
          ([VersionedStreamEvent CounterEvent]
 -> [VersionedStreamEvent CounterEvent]
 -> [VersionedStreamEvent CounterEvent]
 -> [VersionedStreamEvent CounterEvent]
 -> ([VersionedStreamEvent CounterEvent],
     [VersionedStreamEvent CounterEvent],
     [VersionedStreamEvent CounterEvent],
     [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent]
      -> [VersionedStreamEvent CounterEvent]
      -> [VersionedStreamEvent CounterEvent]
      -> ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> EventVersion -> QueryRange UUID EventVersion
forall key position. key -> position -> QueryRange key position
eventsUntil UUID
nil EventVersion
1)
          m ([VersionedStreamEvent CounterEvent]
   -> [VersionedStreamEvent CounterEvent]
   -> [VersionedStreamEvent CounterEvent]
   -> ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent]
      -> [VersionedStreamEvent CounterEvent]
      -> ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID
-> EventVersion -> EventVersion -> QueryRange UUID EventVersion
forall key position.
key -> position -> position -> QueryRange key position
eventsStartingAtUntil UUID
nil EventVersion
1 EventVersion
2)
          m ([VersionedStreamEvent CounterEvent]
   -> [VersionedStreamEvent CounterEvent]
   -> ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent]
      -> ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> EventVersion -> QueryRange UUID EventVersion
forall key position. key -> position -> QueryRange key position
eventsStartingAt UUID
nil EventVersion
2)
          m ([VersionedStreamEvent CounterEvent]
   -> ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> EventVersion -> Int -> QueryRange UUID EventVersion
forall key position.
key -> position -> Int -> QueryRange key position
eventsStartingAtTakeLimit UUID
nil EventVersion
0 Int
2)
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
firstEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> [CounterEvent] -> [CounterEvent]
forall a. Int -> [a] -> [a]
take Int
2 [CounterEvent]
sampleEvents
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
middleEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> [CounterEvent] -> [CounterEvent]
forall a. Int -> [a] -> [a]
take Int
2 (Int -> [CounterEvent] -> [CounterEvent]
forall a. Int -> [a] -> [a]
drop Int
1 [CounterEvent]
sampleEvents)
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
laterEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> [CounterEvent] -> [CounterEvent]
forall a. Int -> [a] -> [a]
drop Int
2 [CounterEvent]
sampleEvents
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
maxEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> [CounterEvent] -> [CounterEvent]
forall a. Int -> [a] -> [a]
take Int
2 [CounterEvent]
sampleEvents

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should return the latest projection" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      StreamProjection UUID EventVersion Counter CounterEvent
projection <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m (StreamProjection UUID EventVersion Counter CounterEvent))
-> IO (StreamProjection UUID EventVersion Counter CounterEvent)
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore' ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m (StreamProjection UUID EventVersion Counter CounterEvent))
 -> IO (StreamProjection UUID EventVersion Counter CounterEvent))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m (StreamProjection UUID EventVersion Counter CounterEvent))
-> IO (StreamProjection UUID EventVersion Counter CounterEvent)
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader ->
        VersionedEventStoreReader m CounterEvent
-> StreamProjection UUID EventVersion Counter CounterEvent
-> m (StreamProjection UUID EventVersion Counter CounterEvent)
forall (m :: * -> *) position key event state.
(Monad m, Num position) =>
EventStoreReader key position m (StreamEvent key position event)
-> StreamProjection key position state event
-> m (StreamProjection key position state event)
getLatestStreamProjection VersionedEventStoreReader m CounterEvent
reader (UUID
-> CounterProjection
-> StreamProjection UUID EventVersion Counter CounterEvent
forall state event.
UUID
-> Projection state event -> VersionedStreamProjection state event
versionedStreamProjection UUID
nil CounterProjection
counterProjection)
      StreamProjection UUID EventVersion Counter CounterEvent -> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection UUID EventVersion Counter CounterEvent
projection Counter -> Counter -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Counter
Counter Int
7
      StreamProjection UUID EventVersion Counter CounterEvent
-> EventVersion
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection UUID EventVersion Counter CounterEvent
projection EventVersion -> EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventVersion
3
      StreamProjection UUID EventVersion Counter CounterEvent -> UUID
forall key position state event.
StreamProjection key position state event -> key
streamProjectionKey StreamProjection UUID EventVersion Counter CounterEvent
projection UUID -> UUID -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` UUID
nil

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should return the latest projection with some starting StreamProjection" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      StreamProjection UUID EventVersion Counter CounterEvent
projection <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m (StreamProjection UUID EventVersion Counter CounterEvent))
-> IO (StreamProjection UUID EventVersion Counter CounterEvent)
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore' ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m (StreamProjection UUID EventVersion Counter CounterEvent))
 -> IO (StreamProjection UUID EventVersion Counter CounterEvent))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m (StreamProjection UUID EventVersion Counter CounterEvent))
-> IO (StreamProjection UUID EventVersion Counter CounterEvent)
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader -> do
        [VersionedStreamEvent CounterEvent]
initialEvents <- VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> EventVersion -> QueryRange UUID EventVersion
forall key position. key -> position -> QueryRange key position
eventsUntil UUID
nil EventVersion
1)
        let initialProjection :: Counter
initialProjection = CounterProjection -> [CounterEvent] -> Counter
forall (t :: * -> *) state event.
Foldable t =>
Projection state event -> t event -> state
latestProjection CounterProjection
counterProjection (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
initialEvents)
        VersionedEventStoreReader m CounterEvent
-> StreamProjection UUID EventVersion Counter CounterEvent
-> m (StreamProjection UUID EventVersion Counter CounterEvent)
forall (m :: * -> *) position key event state.
(Monad m, Num position) =>
EventStoreReader key position m (StreamEvent key position event)
-> StreamProjection key position state event
-> m (StreamProjection key position state event)
getLatestStreamProjection VersionedEventStoreReader m CounterEvent
reader (UUID
-> EventVersion
-> CounterProjection
-> Counter
-> StreamProjection UUID EventVersion Counter CounterEvent
forall key position state event.
key
-> position
-> Projection state event
-> state
-> StreamProjection key position state event
StreamProjection UUID
nil EventVersion
1 CounterProjection
counterProjection Counter
initialProjection)
      StreamProjection UUID EventVersion Counter CounterEvent -> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection UUID EventVersion Counter CounterEvent
projection Counter -> Counter -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Counter
Counter Int
7
      StreamProjection UUID EventVersion Counter CounterEvent
-> EventVersion
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection UUID EventVersion Counter CounterEvent
projection EventVersion -> EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventVersion
3
      StreamProjection UUID EventVersion Counter CounterEvent -> UUID
forall key position state event.
StreamProjection key position state event -> key
streamProjectionKey StreamProjection UUID EventVersion Counter CounterEvent
projection UUID -> UUID -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` UUID
nil

  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when events from multiple UUIDs are inserted" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should have the correct events for each stream" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      ([VersionedStreamEvent CounterEvent]
events1, [VersionedStreamEvent CounterEvent]
events2) <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> IO
     ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStoreExampleEvents ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m ([VersionedStreamEvent CounterEvent],
        [VersionedStreamEvent CounterEvent]))
 -> IO
      ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
-> IO
     ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader ->
        (,) ([VersionedStreamEvent CounterEvent]
 -> [VersionedStreamEvent CounterEvent]
 -> ([VersionedStreamEvent CounterEvent],
     [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent]
      -> ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> QueryRange UUID EventVersion
forall key position. key -> QueryRange key position
allEvents UUID
uuid1) m ([VersionedStreamEvent CounterEvent]
   -> ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> QueryRange UUID EventVersion
forall key position. key -> QueryRange key position
allEvents UUID
uuid2)
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events1) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> CounterEvent
Added (Int -> CounterEvent) -> [Int] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
1, Int
4]
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events2) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> CounterEvent
Added (Int -> CounterEvent) -> [Int] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
2, Int
3, Int
5]
      (VersionedStreamEvent CounterEvent -> UUID
forall key position event. StreamEvent key position event -> key
streamEventKey (VersionedStreamEvent CounterEvent -> UUID)
-> [VersionedStreamEvent CounterEvent] -> [UUID]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events1) [UUID] -> [UUID] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [UUID
uuid1, UUID
uuid1]
      (VersionedStreamEvent CounterEvent -> UUID
forall key position event. StreamEvent key position event -> key
streamEventKey (VersionedStreamEvent CounterEvent -> UUID)
-> [VersionedStreamEvent CounterEvent] -> [UUID]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events2) [UUID] -> [UUID] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [UUID
uuid2, UUID
uuid2, UUID
uuid2]
      (VersionedStreamEvent CounterEvent -> EventVersion
forall key position event.
StreamEvent key position event -> position
streamEventPosition (VersionedStreamEvent CounterEvent -> EventVersion)
-> [VersionedStreamEvent CounterEvent] -> [EventVersion]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events1) [EventVersion] -> [EventVersion] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [EventVersion
0, EventVersion
1]
      (VersionedStreamEvent CounterEvent -> EventVersion
forall key position event.
StreamEvent key position event -> position
streamEventPosition (VersionedStreamEvent CounterEvent -> EventVersion)
-> [VersionedStreamEvent CounterEvent] -> [EventVersion]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events2) [EventVersion] -> [EventVersion] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [EventVersion
0, EventVersion
1, EventVersion
2]

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should return correct event versions" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      ([VersionedStreamEvent CounterEvent]
events1, [VersionedStreamEvent CounterEvent]
events2) <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> IO
     ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStoreExampleEvents ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m ([VersionedStreamEvent CounterEvent],
        [VersionedStreamEvent CounterEvent]))
 -> IO
      ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
-> IO
     ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader ->
        (,)
          ([VersionedStreamEvent CounterEvent]
 -> [VersionedStreamEvent CounterEvent]
 -> ([VersionedStreamEvent CounterEvent],
     [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent]
      -> ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> QueryRange UUID EventVersion
forall key position. key -> QueryRange key position
allEvents UUID
uuid1)
          m ([VersionedStreamEvent CounterEvent]
   -> ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> QueryRange UUID EventVersion
forall key position. key -> QueryRange key position
allEvents UUID
uuid2)
      VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events1 [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [Int -> CounterEvent
Added Int
1, Int -> CounterEvent
Added Int
4]
      VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
events2 [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [Int -> CounterEvent
Added Int
2, Int -> CounterEvent
Added Int
3, Int -> CounterEvent
Added Int
5]

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should return correct events with queries" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      ([VersionedStreamEvent CounterEvent]
firstEvents, [VersionedStreamEvent CounterEvent]
middleEvents, [VersionedStreamEvent CounterEvent]
laterEvents, [VersionedStreamEvent CounterEvent]
maxEvents) <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> IO
     ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStoreExampleEvents ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m ([VersionedStreamEvent CounterEvent],
        [VersionedStreamEvent CounterEvent],
        [VersionedStreamEvent CounterEvent],
        [VersionedStreamEvent CounterEvent]))
 -> IO
      ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
-> IO
     ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader ->
        (,,,)
          ([VersionedStreamEvent CounterEvent]
 -> [VersionedStreamEvent CounterEvent]
 -> [VersionedStreamEvent CounterEvent]
 -> [VersionedStreamEvent CounterEvent]
 -> ([VersionedStreamEvent CounterEvent],
     [VersionedStreamEvent CounterEvent],
     [VersionedStreamEvent CounterEvent],
     [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent]
      -> [VersionedStreamEvent CounterEvent]
      -> [VersionedStreamEvent CounterEvent]
      -> ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> EventVersion -> QueryRange UUID EventVersion
forall key position. key -> position -> QueryRange key position
eventsUntil UUID
uuid1 EventVersion
1)
          m ([VersionedStreamEvent CounterEvent]
   -> [VersionedStreamEvent CounterEvent]
   -> [VersionedStreamEvent CounterEvent]
   -> ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent]
      -> [VersionedStreamEvent CounterEvent]
      -> ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID
-> EventVersion -> EventVersion -> QueryRange UUID EventVersion
forall key position.
key -> position -> position -> QueryRange key position
eventsStartingAtUntil UUID
uuid2 EventVersion
1 EventVersion
2)
          m ([VersionedStreamEvent CounterEvent]
   -> [VersionedStreamEvent CounterEvent]
   -> ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent]
      -> ([VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent],
          [VersionedStreamEvent CounterEvent]))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> EventVersion -> QueryRange UUID EventVersion
forall key position. key -> position -> QueryRange key position
eventsStartingAt UUID
uuid2 EventVersion
2)
          m ([VersionedStreamEvent CounterEvent]
   -> ([VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent],
       [VersionedStreamEvent CounterEvent]))
-> m [VersionedStreamEvent CounterEvent]
-> m ([VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent],
      [VersionedStreamEvent CounterEvent])
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> QueryRange UUID EventVersion
-> m [VersionedStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents VersionedEventStoreReader m CounterEvent
reader (UUID -> EventVersion -> Int -> QueryRange UUID EventVersion
forall key position.
key -> position -> Int -> QueryRange key position
eventsStartingAtTakeLimit UUID
uuid1 EventVersion
1 Int
1)
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
firstEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [Int -> CounterEvent
Added Int
1, Int -> CounterEvent
Added Int
4]
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
middleEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [Int -> CounterEvent
Added Int
3, Int -> CounterEvent
Added Int
5]
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
laterEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [Int -> CounterEvent
Added Int
5]
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> [VersionedStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [VersionedStreamEvent CounterEvent]
maxEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [Int -> CounterEvent
Added Int
4]

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should produce the correct projections" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      (StreamProjection UUID EventVersion Counter CounterEvent
proj1, StreamProjection UUID EventVersion Counter CounterEvent
proj2) <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m (StreamProjection UUID EventVersion Counter CounterEvent,
       StreamProjection UUID EventVersion Counter CounterEvent))
-> IO
     (StreamProjection UUID EventVersion Counter CounterEvent,
      StreamProjection UUID EventVersion Counter CounterEvent)
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStoreExampleEvents ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m (StreamProjection UUID EventVersion Counter CounterEvent,
        StreamProjection UUID EventVersion Counter CounterEvent))
 -> IO
      (StreamProjection UUID EventVersion Counter CounterEvent,
       StreamProjection UUID EventVersion Counter CounterEvent))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m (StreamProjection UUID EventVersion Counter CounterEvent,
          StreamProjection UUID EventVersion Counter CounterEvent))
-> IO
     (StreamProjection UUID EventVersion Counter CounterEvent,
      StreamProjection UUID EventVersion Counter CounterEvent)
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
reader ->
        (,)
          (StreamProjection UUID EventVersion Counter CounterEvent
 -> StreamProjection UUID EventVersion Counter CounterEvent
 -> (StreamProjection UUID EventVersion Counter CounterEvent,
     StreamProjection UUID EventVersion Counter CounterEvent))
-> m (StreamProjection UUID EventVersion Counter CounterEvent)
-> m (StreamProjection UUID EventVersion Counter CounterEvent
      -> (StreamProjection UUID EventVersion Counter CounterEvent,
          StreamProjection UUID EventVersion Counter CounterEvent))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VersionedEventStoreReader m CounterEvent
-> StreamProjection UUID EventVersion Counter CounterEvent
-> m (StreamProjection UUID EventVersion Counter CounterEvent)
forall (m :: * -> *) position key event state.
(Monad m, Num position) =>
EventStoreReader key position m (StreamEvent key position event)
-> StreamProjection key position state event
-> m (StreamProjection key position state event)
getLatestStreamProjection VersionedEventStoreReader m CounterEvent
reader (UUID
-> CounterProjection
-> StreamProjection UUID EventVersion Counter CounterEvent
forall state event.
UUID
-> Projection state event -> VersionedStreamProjection state event
versionedStreamProjection UUID
uuid1 CounterProjection
counterProjection)
          m (StreamProjection UUID EventVersion Counter CounterEvent
   -> (StreamProjection UUID EventVersion Counter CounterEvent,
       StreamProjection UUID EventVersion Counter CounterEvent))
-> m (StreamProjection UUID EventVersion Counter CounterEvent)
-> m (StreamProjection UUID EventVersion Counter CounterEvent,
      StreamProjection UUID EventVersion Counter CounterEvent)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreReader m CounterEvent
-> StreamProjection UUID EventVersion Counter CounterEvent
-> m (StreamProjection UUID EventVersion Counter CounterEvent)
forall (m :: * -> *) position key event state.
(Monad m, Num position) =>
EventStoreReader key position m (StreamEvent key position event)
-> StreamProjection key position state event
-> m (StreamProjection key position state event)
getLatestStreamProjection VersionedEventStoreReader m CounterEvent
reader (UUID
-> CounterProjection
-> StreamProjection UUID EventVersion Counter CounterEvent
forall state event.
UUID
-> Projection state event -> VersionedStreamProjection state event
versionedStreamProjection UUID
uuid2 CounterProjection
counterProjection)
      (StreamProjection UUID EventVersion Counter CounterEvent -> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection UUID EventVersion Counter CounterEvent
proj1, StreamProjection UUID EventVersion Counter CounterEvent
-> EventVersion
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection UUID EventVersion Counter CounterEvent
proj1) (Counter, EventVersion) -> (Counter, EventVersion) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int -> Counter
Counter Int
5, EventVersion
1)
      (StreamProjection UUID EventVersion Counter CounterEvent -> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection UUID EventVersion Counter CounterEvent
proj2, StreamProjection UUID EventVersion Counter CounterEvent
-> EventVersion
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection UUID EventVersion Counter CounterEvent
proj2) (Counter, EventVersion) -> (Counter, EventVersion) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (Int -> Counter
Counter Int
10, EventVersion
2)

  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
describe String
"can handle event storage errors" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"rejects some writes when event store isn't created" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      (Either (EventWriteError EventVersion) EventVersion
err1, Either (EventWriteError EventVersion) EventVersion
err2) <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m (Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion))
-> IO
     (Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion)
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m (Either (EventWriteError EventVersion) EventVersion,
        Either (EventWriteError EventVersion) EventVersion))
 -> IO
      (Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m (Either (EventWriteError EventVersion) EventVersion,
          Either (EventWriteError EventVersion) EventVersion))
-> IO
     (Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion)
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
_ ->
        (,)
          (Either (EventWriteError EventVersion) EventVersion
 -> Either (EventWriteError EventVersion) EventVersion
 -> (Either (EventWriteError EventVersion) EventVersion,
     Either (EventWriteError EventVersion) EventVersion))
-> m (Either (EventWriteError EventVersion) EventVersion)
-> m (Either (EventWriteError EventVersion) EventVersion
      -> (Either (EventWriteError EventVersion) EventVersion,
          Either (EventWriteError EventVersion) EventVersion))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
StreamExists [Int -> CounterEvent
Added Int
1]
          m (Either (EventWriteError EventVersion) EventVersion
   -> (Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion))
-> m (Either (EventWriteError EventVersion) EventVersion)
-> m (Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil (EventVersion -> ExpectedPosition EventVersion
forall position. position -> ExpectedPosition position
ExactPosition EventVersion
0) [Int -> CounterEvent
Added Int
1]
      Either (EventWriteError EventVersion) EventVersion
err1 Either (EventWriteError EventVersion) EventVersion
-> Either (EventWriteError EventVersion) EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventWriteError EventVersion
-> Either (EventWriteError EventVersion) EventVersion
forall a b. a -> Either a b
Left (EventVersion -> EventWriteError EventVersion
forall position. position -> EventWriteError position
EventStreamNotAtExpectedVersion (-EventVersion
1))
      Either (EventWriteError EventVersion) EventVersion
err2 Either (EventWriteError EventVersion) EventVersion
-> Either (EventWriteError EventVersion) EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventWriteError EventVersion
-> Either (EventWriteError EventVersion) EventVersion
forall a b. a -> Either a b
Left (EventVersion -> EventWriteError EventVersion
forall position. position -> EventWriteError position
EventStreamNotAtExpectedVersion (-EventVersion
1))

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should be able to store events starting with an empty stream" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m (Either (EventWriteError EventVersion) EventVersion))
-> IO (Either (EventWriteError EventVersion) EventVersion)
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore (\VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
_ -> VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
NoStream [Int -> CounterEvent
Added Int
1]) IO (Either (EventWriteError EventVersion) EventVersion)
-> Either (EventWriteError EventVersion) EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => IO a -> a -> IO ()
`shouldReturn` EventVersion -> Either (EventWriteError EventVersion) EventVersion
forall a b. b -> Either a b
Right EventVersion
0

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should reject storing events sometimes with a stream" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      (Either (EventWriteError EventVersion) EventVersion
err1, Either (EventWriteError EventVersion) EventVersion
err2, Either (EventWriteError EventVersion) EventVersion
err3) <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m (Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion))
-> IO
     (Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion)
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m (Either (EventWriteError EventVersion) EventVersion,
        Either (EventWriteError EventVersion) EventVersion,
        Either (EventWriteError EventVersion) EventVersion))
 -> IO
      (Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m (Either (EventWriteError EventVersion) EventVersion,
          Either (EventWriteError EventVersion) EventVersion,
          Either (EventWriteError EventVersion) EventVersion))
-> IO
     (Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion)
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
_ ->
        (,,)
          (Either (EventWriteError EventVersion) EventVersion
 -> Either (EventWriteError EventVersion) EventVersion
 -> Either (EventWriteError EventVersion) EventVersion
 -> (Either (EventWriteError EventVersion) EventVersion,
     Either (EventWriteError EventVersion) EventVersion,
     Either (EventWriteError EventVersion) EventVersion))
-> m (Either (EventWriteError EventVersion) EventVersion)
-> m (Either (EventWriteError EventVersion) EventVersion
      -> Either (EventWriteError EventVersion) EventVersion
      -> (Either (EventWriteError EventVersion) EventVersion,
          Either (EventWriteError EventVersion) EventVersion,
          Either (EventWriteError EventVersion) EventVersion))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
NoStream [Int -> CounterEvent
Added Int
1]
          m (Either (EventWriteError EventVersion) EventVersion
   -> Either (EventWriteError EventVersion) EventVersion
   -> (Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion))
-> m (Either (EventWriteError EventVersion) EventVersion)
-> m (Either (EventWriteError EventVersion) EventVersion
      -> (Either (EventWriteError EventVersion) EventVersion,
          Either (EventWriteError EventVersion) EventVersion,
          Either (EventWriteError EventVersion) EventVersion))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
NoStream [Int -> CounterEvent
Added Int
1]
          m (Either (EventWriteError EventVersion) EventVersion
   -> (Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion,
       Either (EventWriteError EventVersion) EventVersion))
-> m (Either (EventWriteError EventVersion) EventVersion)
-> m (Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion,
      Either (EventWriteError EventVersion) EventVersion)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil (EventVersion -> ExpectedPosition EventVersion
forall position. position -> ExpectedPosition position
ExactPosition EventVersion
1) [Int -> CounterEvent
Added Int
1]
      Either (EventWriteError EventVersion) EventVersion
err1 Either (EventWriteError EventVersion) EventVersion
-> Either (EventWriteError EventVersion) EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventVersion -> Either (EventWriteError EventVersion) EventVersion
forall a b. b -> Either a b
Right EventVersion
0
      Either (EventWriteError EventVersion) EventVersion
err2 Either (EventWriteError EventVersion) EventVersion
-> Either (EventWriteError EventVersion) EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventWriteError EventVersion
-> Either (EventWriteError EventVersion) EventVersion
forall a b. a -> Either a b
Left (EventVersion -> EventWriteError EventVersion
forall position. position -> EventWriteError position
EventStreamNotAtExpectedVersion EventVersion
0)
      Either (EventWriteError EventVersion) EventVersion
err3 Either (EventWriteError EventVersion) EventVersion
-> Either (EventWriteError EventVersion) EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventWriteError EventVersion
-> Either (EventWriteError EventVersion) EventVersion
forall a b. a -> Either a b
Left (EventVersion -> EventWriteError EventVersion
forall position. position -> EventWriteError position
EventStreamNotAtExpectedVersion EventVersion
0)

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should accepts storing events sometimes with a stream" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      [Either (EventWriteError EventVersion) EventVersion]
errors <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> m [Either (EventWriteError EventVersion) EventVersion])
-> IO [Either (EventWriteError EventVersion) EventVersion]
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent -> m a)
-> IO a
withStore ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> m [Either (EventWriteError EventVersion) EventVersion])
 -> IO [Either (EventWriteError EventVersion) EventVersion])
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> m [Either (EventWriteError EventVersion) EventVersion])
-> IO [Either (EventWriteError EventVersion) EventVersion]
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
_ ->
        [m (Either (EventWriteError EventVersion) EventVersion)]
-> m [Either (EventWriteError EventVersion) EventVersion]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence
          [ VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
NoStream [Int -> CounterEvent
Added Int
1],
            VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
AnyPosition [Int -> CounterEvent
Added Int
1],
            VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil (EventVersion -> ExpectedPosition EventVersion
forall position. position -> ExpectedPosition position
ExactPosition EventVersion
1) [Int -> CounterEvent
Added Int
1],
            VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
StreamExists [Int -> CounterEvent
Added Int
1]
          ]
      [Either (EventWriteError EventVersion) EventVersion]
errors [Either (EventWriteError EventVersion) EventVersion]
-> [Either (EventWriteError EventVersion) EventVersion] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [EventVersion -> Either (EventWriteError EventVersion) EventVersion
forall a b. b -> Either a b
Right EventVersion
0, EventVersion -> Either (EventWriteError EventVersion) EventVersion
forall a b. b -> Either a b
Right EventVersion
1, EventVersion -> Either (EventWriteError EventVersion) EventVersion
forall a b. b -> Either a b
Right EventVersion
2, EventVersion -> Either (EventWriteError EventVersion) EventVersion
forall a b. b -> Either a b
Right EventVersion
3]

newtype GlobalStreamEventStoreRunner m
  = GlobalStreamEventStoreRunner
      (forall a. (VersionedEventStoreWriter m CounterEvent -> GlobalEventStoreReader m CounterEvent -> m a) -> IO a)

globalStreamEventStoreSpec ::
  (Monad m) =>
  GlobalStreamEventStoreRunner m ->
  Spec
globalStreamEventStoreSpec :: forall (m :: * -> *).
Monad m =>
GlobalStreamEventStoreRunner m -> Spec
globalStreamEventStoreSpec (GlobalStreamEventStoreRunner forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent -> m a)
-> IO a
withStore) = do
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when the event store is empty" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"shouldn't have any events" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      [GlobalStreamEvent CounterEvent]
events <- (VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> m [GlobalStreamEvent CounterEvent])
-> IO [GlobalStreamEvent CounterEvent]
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent -> m a)
-> IO a
withStore (\VersionedEventStoreWriter m CounterEvent
_ GlobalEventStoreReader m CounterEvent
globalReader -> GlobalEventStoreReader m CounterEvent
-> QueryRange () SequenceNumber
-> m [GlobalStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents GlobalEventStoreReader m CounterEvent
globalReader (() -> QueryRange () SequenceNumber
forall key position. key -> QueryRange key position
allEvents ()))
      [GlobalStreamEvent CounterEvent] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [GlobalStreamEvent CounterEvent]
events Int -> Int -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int
0

  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when events from multiple UUIDs are inserted" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should have the correct events in global order" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      [GlobalStreamEvent CounterEvent]
events <- (VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> m [GlobalStreamEvent CounterEvent])
-> IO [GlobalStreamEvent CounterEvent]
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent -> m a)
-> IO a
withStore ((VersionedEventStoreWriter m CounterEvent
  -> GlobalEventStoreReader m CounterEvent
  -> m [GlobalStreamEvent CounterEvent])
 -> IO [GlobalStreamEvent CounterEvent])
-> (VersionedEventStoreWriter m CounterEvent
    -> GlobalEventStoreReader m CounterEvent
    -> m [GlobalStreamEvent CounterEvent])
-> IO [GlobalStreamEvent CounterEvent]
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer GlobalEventStoreReader m CounterEvent
globalReader -> do
        VersionedEventStoreWriter m CounterEvent -> m ()
forall (m :: * -> *).
Monad m =>
VersionedEventStoreWriter m CounterEvent -> m ()
insertExampleEvents VersionedEventStoreWriter m CounterEvent
writer
        GlobalEventStoreReader m CounterEvent
-> QueryRange () SequenceNumber
-> m [GlobalStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents GlobalEventStoreReader m CounterEvent
globalReader (() -> QueryRange () SequenceNumber
forall key position. key -> QueryRange key position
allEvents ())
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> (GlobalStreamEvent CounterEvent
    -> VersionedStreamEvent CounterEvent)
-> GlobalStreamEvent CounterEvent
-> CounterEvent
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalStreamEvent CounterEvent -> VersionedStreamEvent CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (GlobalStreamEvent CounterEvent -> CounterEvent)
-> [GlobalStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
events) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> CounterEvent
Added (Int -> CounterEvent) -> [Int] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
1 .. Int
5]
      (VersionedStreamEvent CounterEvent -> UUID
forall key position event. StreamEvent key position event -> key
streamEventKey (VersionedStreamEvent CounterEvent -> UUID)
-> (GlobalStreamEvent CounterEvent
    -> VersionedStreamEvent CounterEvent)
-> GlobalStreamEvent CounterEvent
-> UUID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalStreamEvent CounterEvent -> VersionedStreamEvent CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (GlobalStreamEvent CounterEvent -> UUID)
-> [GlobalStreamEvent CounterEvent] -> [UUID]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
events) [UUID] -> [UUID] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [UUID
uuid1, UUID
uuid2, UUID
uuid2, UUID
uuid1, UUID
uuid2]
      (VersionedStreamEvent CounterEvent -> EventVersion
forall key position event.
StreamEvent key position event -> position
streamEventPosition (VersionedStreamEvent CounterEvent -> EventVersion)
-> (GlobalStreamEvent CounterEvent
    -> VersionedStreamEvent CounterEvent)
-> GlobalStreamEvent CounterEvent
-> EventVersion
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalStreamEvent CounterEvent -> VersionedStreamEvent CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (GlobalStreamEvent CounterEvent -> EventVersion)
-> [GlobalStreamEvent CounterEvent] -> [EventVersion]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
events) [EventVersion] -> [EventVersion] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [EventVersion
0, EventVersion
0, EventVersion
1, EventVersion
1, EventVersion
2]
      (GlobalStreamEvent CounterEvent -> SequenceNumber
forall key position event.
StreamEvent key position event -> position
streamEventPosition (GlobalStreamEvent CounterEvent -> SequenceNumber)
-> [GlobalStreamEvent CounterEvent] -> [SequenceNumber]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
events) [SequenceNumber] -> [SequenceNumber] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [SequenceNumber
1 .. SequenceNumber
5]

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should work with global projections" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      (StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
proj1, StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
proj2) <- (VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> m (StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent),
       StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> IO
     (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent),
      StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent -> m a)
-> IO a
withStore ((VersionedEventStoreWriter m CounterEvent
  -> GlobalEventStoreReader m CounterEvent
  -> m (StreamProjection
          () SequenceNumber Counter (VersionedStreamEvent CounterEvent),
        StreamProjection
          () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
 -> IO
      (StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent),
       StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> (VersionedEventStoreWriter m CounterEvent
    -> GlobalEventStoreReader m CounterEvent
    -> m (StreamProjection
            () SequenceNumber Counter (VersionedStreamEvent CounterEvent),
          StreamProjection
            () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> IO
     (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent),
      StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer GlobalEventStoreReader m CounterEvent
globalReader -> do
        VersionedEventStoreWriter m CounterEvent -> m ()
forall (m :: * -> *).
Monad m =>
VersionedEventStoreWriter m CounterEvent -> m ()
insertExampleEvents VersionedEventStoreWriter m CounterEvent
writer
        StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
p1 <- GlobalEventStoreReader m CounterEvent
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> m (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall (m :: * -> *) position key event state.
(Monad m, Num position) =>
EventStoreReader key position m (StreamEvent key position event)
-> StreamProjection key position state event
-> m (StreamProjection key position state event)
getLatestStreamProjection GlobalEventStoreReader m CounterEvent
globalReader (Projection Counter (VersionedStreamEvent CounterEvent)
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
forall state event.
Projection state (VersionedStreamEvent event)
-> GlobalStreamProjection state event
globalStreamProjection Projection Counter (VersionedStreamEvent CounterEvent)
counterGlobalProjection)
        Either (EventWriteError EventVersion) EventVersion
_ <- VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
uuid1 ExpectedPosition EventVersion
forall position. ExpectedPosition position
AnyPosition [Int -> CounterEvent
Added Int
10, Int -> CounterEvent
Added Int
20]
        StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
p2 <- GlobalEventStoreReader m CounterEvent
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> m (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall (m :: * -> *) position key event state.
(Monad m, Num position) =>
EventStoreReader key position m (StreamEvent key position event)
-> StreamProjection key position state event
-> m (StreamProjection key position state event)
getLatestStreamProjection GlobalEventStoreReader m CounterEvent
globalReader StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
p1
        (StreamProjection
   () SequenceNumber Counter (VersionedStreamEvent CounterEvent),
 StreamProjection
   () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
-> m (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent),
      StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
p1, StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
p2)

      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> SequenceNumber
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
proj1 SequenceNumber -> SequenceNumber -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` SequenceNumber
5
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> SequenceNumber
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
proj2 SequenceNumber -> SequenceNumber -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` SequenceNumber
7

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should handle queries" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      ([GlobalStreamEvent CounterEvent]
firstEvents, [GlobalStreamEvent CounterEvent]
middleEvents, [GlobalStreamEvent CounterEvent]
laterEvents, [GlobalStreamEvent CounterEvent]
maxEvents) <- (VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> m ([GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent]))
-> IO
     ([GlobalStreamEvent CounterEvent],
      [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
      [GlobalStreamEvent CounterEvent])
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent -> m a)
-> IO a
withStore ((VersionedEventStoreWriter m CounterEvent
  -> GlobalEventStoreReader m CounterEvent
  -> m ([GlobalStreamEvent CounterEvent],
        [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
        [GlobalStreamEvent CounterEvent]))
 -> IO
      ([GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent]))
-> (VersionedEventStoreWriter m CounterEvent
    -> GlobalEventStoreReader m CounterEvent
    -> m ([GlobalStreamEvent CounterEvent],
          [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
          [GlobalStreamEvent CounterEvent]))
-> IO
     ([GlobalStreamEvent CounterEvent],
      [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
      [GlobalStreamEvent CounterEvent])
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer GlobalEventStoreReader m CounterEvent
globalReader -> do
        VersionedEventStoreWriter m CounterEvent -> m ()
forall (m :: * -> *).
Monad m =>
VersionedEventStoreWriter m CounterEvent -> m ()
insertExampleEvents VersionedEventStoreWriter m CounterEvent
writer
        (,,,)
          ([GlobalStreamEvent CounterEvent]
 -> [GlobalStreamEvent CounterEvent]
 -> [GlobalStreamEvent CounterEvent]
 -> [GlobalStreamEvent CounterEvent]
 -> ([GlobalStreamEvent CounterEvent],
     [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
     [GlobalStreamEvent CounterEvent]))
-> m [GlobalStreamEvent CounterEvent]
-> m ([GlobalStreamEvent CounterEvent]
      -> [GlobalStreamEvent CounterEvent]
      -> [GlobalStreamEvent CounterEvent]
      -> ([GlobalStreamEvent CounterEvent],
          [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
          [GlobalStreamEvent CounterEvent]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GlobalEventStoreReader m CounterEvent
-> QueryRange () SequenceNumber
-> m [GlobalStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents GlobalEventStoreReader m CounterEvent
globalReader (() -> SequenceNumber -> QueryRange () SequenceNumber
forall key position. key -> position -> QueryRange key position
eventsUntil () SequenceNumber
2)
          m ([GlobalStreamEvent CounterEvent]
   -> [GlobalStreamEvent CounterEvent]
   -> [GlobalStreamEvent CounterEvent]
   -> ([GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent]))
-> m [GlobalStreamEvent CounterEvent]
-> m ([GlobalStreamEvent CounterEvent]
      -> [GlobalStreamEvent CounterEvent]
      -> ([GlobalStreamEvent CounterEvent],
          [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
          [GlobalStreamEvent CounterEvent]))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GlobalEventStoreReader m CounterEvent
-> QueryRange () SequenceNumber
-> m [GlobalStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents GlobalEventStoreReader m CounterEvent
globalReader (()
-> SequenceNumber -> SequenceNumber -> QueryRange () SequenceNumber
forall key position.
key -> position -> position -> QueryRange key position
eventsStartingAtUntil () SequenceNumber
2 SequenceNumber
3)
          m ([GlobalStreamEvent CounterEvent]
   -> [GlobalStreamEvent CounterEvent]
   -> ([GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent]))
-> m [GlobalStreamEvent CounterEvent]
-> m ([GlobalStreamEvent CounterEvent]
      -> ([GlobalStreamEvent CounterEvent],
          [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
          [GlobalStreamEvent CounterEvent]))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GlobalEventStoreReader m CounterEvent
-> QueryRange () SequenceNumber
-> m [GlobalStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents GlobalEventStoreReader m CounterEvent
globalReader (() -> SequenceNumber -> QueryRange () SequenceNumber
forall key position. key -> position -> QueryRange key position
eventsStartingAt () SequenceNumber
3)
          m ([GlobalStreamEvent CounterEvent]
   -> ([GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
       [GlobalStreamEvent CounterEvent]))
-> m [GlobalStreamEvent CounterEvent]
-> m ([GlobalStreamEvent CounterEvent],
      [GlobalStreamEvent CounterEvent], [GlobalStreamEvent CounterEvent],
      [GlobalStreamEvent CounterEvent])
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GlobalEventStoreReader m CounterEvent
-> QueryRange () SequenceNumber
-> m [GlobalStreamEvent CounterEvent]
forall key position (m :: * -> *) event.
EventStoreReader key position m event
-> QueryRange key position -> m [event]
getEvents GlobalEventStoreReader m CounterEvent
globalReader (() -> SequenceNumber -> Int -> QueryRange () SequenceNumber
forall key position.
key -> position -> Int -> QueryRange key position
eventsStartingAtTakeLimit () SequenceNumber
2 Int
3)

      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> (GlobalStreamEvent CounterEvent
    -> VersionedStreamEvent CounterEvent)
-> GlobalStreamEvent CounterEvent
-> CounterEvent
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalStreamEvent CounterEvent -> VersionedStreamEvent CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (GlobalStreamEvent CounterEvent -> CounterEvent)
-> [GlobalStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
firstEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> CounterEvent
Added (Int -> CounterEvent) -> [Int] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
1 .. Int
2]
      (GlobalStreamEvent CounterEvent -> SequenceNumber
forall key position event.
StreamEvent key position event -> position
streamEventPosition (GlobalStreamEvent CounterEvent -> SequenceNumber)
-> [GlobalStreamEvent CounterEvent] -> [SequenceNumber]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
firstEvents) [SequenceNumber] -> [SequenceNumber] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [SequenceNumber
1 .. SequenceNumber
2]
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> (GlobalStreamEvent CounterEvent
    -> VersionedStreamEvent CounterEvent)
-> GlobalStreamEvent CounterEvent
-> CounterEvent
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalStreamEvent CounterEvent -> VersionedStreamEvent CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (GlobalStreamEvent CounterEvent -> CounterEvent)
-> [GlobalStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
middleEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> CounterEvent
Added (Int -> CounterEvent) -> [Int] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
2 .. Int
3]
      (GlobalStreamEvent CounterEvent -> SequenceNumber
forall key position event.
StreamEvent key position event -> position
streamEventPosition (GlobalStreamEvent CounterEvent -> SequenceNumber)
-> [GlobalStreamEvent CounterEvent] -> [SequenceNumber]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
middleEvents) [SequenceNumber] -> [SequenceNumber] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [SequenceNumber
2 .. SequenceNumber
3]
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> (GlobalStreamEvent CounterEvent
    -> VersionedStreamEvent CounterEvent)
-> GlobalStreamEvent CounterEvent
-> CounterEvent
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalStreamEvent CounterEvent -> VersionedStreamEvent CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (GlobalStreamEvent CounterEvent -> CounterEvent)
-> [GlobalStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
laterEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> CounterEvent
Added (Int -> CounterEvent) -> [Int] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
3 .. Int
5]
      (GlobalStreamEvent CounterEvent -> SequenceNumber
forall key position event.
StreamEvent key position event -> position
streamEventPosition (GlobalStreamEvent CounterEvent -> SequenceNumber)
-> [GlobalStreamEvent CounterEvent] -> [SequenceNumber]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
laterEvents) [SequenceNumber] -> [SequenceNumber] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [SequenceNumber
3 .. SequenceNumber
5]
      (VersionedStreamEvent CounterEvent -> CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (VersionedStreamEvent CounterEvent -> CounterEvent)
-> (GlobalStreamEvent CounterEvent
    -> VersionedStreamEvent CounterEvent)
-> GlobalStreamEvent CounterEvent
-> CounterEvent
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalStreamEvent CounterEvent -> VersionedStreamEvent CounterEvent
forall key position event. StreamEvent key position event -> event
streamEventEvent (GlobalStreamEvent CounterEvent -> CounterEvent)
-> [GlobalStreamEvent CounterEvent] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
maxEvents) [CounterEvent] -> [CounterEvent] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> CounterEvent
Added (Int -> CounterEvent) -> [Int] -> [CounterEvent]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
2 .. Int
4]
      (GlobalStreamEvent CounterEvent -> SequenceNumber
forall key position event.
StreamEvent key position event -> position
streamEventPosition (GlobalStreamEvent CounterEvent -> SequenceNumber)
-> [GlobalStreamEvent CounterEvent] -> [SequenceNumber]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [GlobalStreamEvent CounterEvent]
maxEvents) [SequenceNumber] -> [SequenceNumber] -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` [SequenceNumber
2 .. SequenceNumber
4]

insertExampleEvents ::
  (Monad m) =>
  VersionedEventStoreWriter m CounterEvent ->
  m ()
insertExampleEvents :: forall (m :: * -> *).
Monad m =>
VersionedEventStoreWriter m CounterEvent -> m ()
insertExampleEvents VersionedEventStoreWriter m CounterEvent
store = do
  m (Either (EventWriteError EventVersion) EventVersion) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Either (EventWriteError EventVersion) EventVersion) -> m ())
-> m (Either (EventWriteError EventVersion) EventVersion) -> m ()
forall a b. (a -> b) -> a -> b
$ VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
store UUID
uuid1 ExpectedPosition EventVersion
forall position. ExpectedPosition position
NoStream [Int -> CounterEvent
Added Int
1]
  m (Either (EventWriteError EventVersion) EventVersion) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Either (EventWriteError EventVersion) EventVersion) -> m ())
-> m (Either (EventWriteError EventVersion) EventVersion) -> m ()
forall a b. (a -> b) -> a -> b
$ VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
store UUID
uuid2 ExpectedPosition EventVersion
forall position. ExpectedPosition position
NoStream [Int -> CounterEvent
Added Int
2, Int -> CounterEvent
Added Int
3]
  m (Either (EventWriteError EventVersion) EventVersion) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Either (EventWriteError EventVersion) EventVersion) -> m ())
-> m (Either (EventWriteError EventVersion) EventVersion) -> m ()
forall a b. (a -> b) -> a -> b
$ VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
store UUID
uuid1 (EventVersion -> ExpectedPosition EventVersion
forall position. position -> ExpectedPosition position
ExactPosition EventVersion
0) [Int -> CounterEvent
Added Int
4]
  m (Either (EventWriteError EventVersion) EventVersion) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Either (EventWriteError EventVersion) EventVersion) -> m ())
-> m (Either (EventWriteError EventVersion) EventVersion) -> m ()
forall a b. (a -> b) -> a -> b
$ VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
store UUID
uuid2 (EventVersion -> ExpectedPosition EventVersion
forall position. position -> ExpectedPosition position
ExactPosition EventVersion
1) [Int -> CounterEvent
Added Int
5]

uuid1 :: UUID
uuid1 :: UUID
uuid1 = Integer -> UUID
uuidFromInteger Integer
1

uuid2 :: UUID
uuid2 :: UUID
uuid2 = Integer -> UUID
uuidFromInteger Integer
2

newtype VersionedProjectionCacheRunner m
  = VersionedProjectionCacheRunner
      ( forall a.
        ( VersionedEventStoreWriter m CounterEvent ->
          VersionedEventStoreReader m CounterEvent ->
          VersionedProjectionCache Counter m ->
          m a
        ) ->
        IO a
      )

versionedProjectionCacheSpec ::
  (Monad m) =>
  VersionedProjectionCacheRunner m ->
  Spec
versionedProjectionCacheSpec :: forall (m :: * -> *).
Monad m =>
VersionedProjectionCacheRunner m -> Spec
versionedProjectionCacheSpec (VersionedProjectionCacheRunner forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> VersionedProjectionCache Counter m
 -> m a)
-> IO a
withStoreAndCache) = do
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when the store is empty" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should be able to store and load simple projections" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      Maybe (EventVersion, Counter)
snapshot <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> VersionedProjectionCache Counter m
 -> m (Maybe (EventVersion, Counter)))
-> IO (Maybe (EventVersion, Counter))
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> VersionedProjectionCache Counter m
 -> m a)
-> IO a
withStoreAndCache ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> VersionedProjectionCache Counter m
  -> m (Maybe (EventVersion, Counter)))
 -> IO (Maybe (EventVersion, Counter)))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> VersionedProjectionCache Counter m
    -> m (Maybe (EventVersion, Counter)))
-> IO (Maybe (EventVersion, Counter))
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ VersionedEventStoreReader m CounterEvent
_ VersionedProjectionCache Counter m
cache -> do
        VersionedProjectionCache Counter m
-> UUID -> EventVersion -> Counter -> m ()
forall key position serialized (m :: * -> *).
ProjectionCache key position serialized m
-> key -> position -> serialized -> m ()
storeProjectionSnapshot VersionedProjectionCache Counter m
cache UUID
nil EventVersion
4 (Int -> Counter
Counter Int
100)
        VersionedProjectionCache Counter m
-> UUID -> m (Maybe (EventVersion, Counter))
forall key position serialized (m :: * -> *).
ProjectionCache key position serialized m
-> key -> m (Maybe (position, serialized))
loadProjectionSnapshot VersionedProjectionCache Counter m
cache UUID
nil
      Maybe (EventVersion, Counter)
snapshot Maybe (EventVersion, Counter)
-> Maybe (EventVersion, Counter) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (EventVersion, Counter) -> Maybe (EventVersion, Counter)
forall a. a -> Maybe a
Just (EventVersion
4, Int -> Counter
Counter Int
100)

  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when the store has some events in one stream" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should load from a stream of events" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      StreamProjection UUID EventVersion Counter CounterEvent
snapshot <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> VersionedProjectionCache Counter m
 -> m (StreamProjection UUID EventVersion Counter CounterEvent))
-> IO (StreamProjection UUID EventVersion Counter CounterEvent)
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> VersionedProjectionCache Counter m
 -> m a)
-> IO a
withStoreAndCache ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> VersionedProjectionCache Counter m
  -> m (StreamProjection UUID EventVersion Counter CounterEvent))
 -> IO (StreamProjection UUID EventVersion Counter CounterEvent))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> VersionedProjectionCache Counter m
    -> m (StreamProjection UUID EventVersion Counter CounterEvent))
-> IO (StreamProjection UUID EventVersion Counter CounterEvent)
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
reader VersionedProjectionCache Counter m
cache -> do
        Either (EventWriteError EventVersion) EventVersion
_ <- VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
AnyPosition [Int -> CounterEvent
Added Int
1, Int -> CounterEvent
Added Int
2]
        VersionedEventStoreReader m CounterEvent
-> VersionedProjectionCache Counter m
-> StreamProjection UUID EventVersion Counter CounterEvent
-> m (StreamProjection UUID EventVersion Counter CounterEvent)
forall (m :: * -> *) event state.
Monad m =>
VersionedEventStoreReader m event
-> VersionedProjectionCache state m
-> VersionedStreamProjection state event
-> m (VersionedStreamProjection state event)
getLatestVersionedProjectionWithCache VersionedEventStoreReader m CounterEvent
reader VersionedProjectionCache Counter m
cache (UUID
-> CounterProjection
-> StreamProjection UUID EventVersion Counter CounterEvent
forall state event.
UUID
-> Projection state event -> VersionedStreamProjection state event
versionedStreamProjection UUID
nil CounterProjection
counterProjection)
      StreamProjection UUID EventVersion Counter CounterEvent
-> EventVersion
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection UUID EventVersion Counter CounterEvent
snapshot EventVersion -> EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventVersion
1
      StreamProjection UUID EventVersion Counter CounterEvent -> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection UUID EventVersion Counter CounterEvent
snapshot Counter -> Counter -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Counter
Counter Int
3

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should work with updateProjectionCache" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      StreamProjection UUID EventVersion Counter CounterEvent
snapshot <- (VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> VersionedProjectionCache Counter m
 -> m (StreamProjection UUID EventVersion Counter CounterEvent))
-> IO (StreamProjection UUID EventVersion Counter CounterEvent)
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> VersionedEventStoreReader m CounterEvent
 -> VersionedProjectionCache Counter m
 -> m a)
-> IO a
withStoreAndCache ((VersionedEventStoreWriter m CounterEvent
  -> VersionedEventStoreReader m CounterEvent
  -> VersionedProjectionCache Counter m
  -> m (StreamProjection UUID EventVersion Counter CounterEvent))
 -> IO (StreamProjection UUID EventVersion Counter CounterEvent))
-> (VersionedEventStoreWriter m CounterEvent
    -> VersionedEventStoreReader m CounterEvent
    -> VersionedProjectionCache Counter m
    -> m (StreamProjection UUID EventVersion Counter CounterEvent))
-> IO (StreamProjection UUID EventVersion Counter CounterEvent)
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer VersionedEventStoreReader m CounterEvent
reader VersionedProjectionCache Counter m
cache -> do
        Either (EventWriteError EventVersion) EventVersion
_ <- VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
AnyPosition [Int -> CounterEvent
Added Int
1, Int -> CounterEvent
Added Int
2, Int -> CounterEvent
Added Int
3]
        VersionedEventStoreReader m CounterEvent
-> VersionedProjectionCache Counter m
-> StreamProjection UUID EventVersion Counter CounterEvent
-> m ()
forall (m :: * -> *) event state.
Monad m =>
VersionedEventStoreReader m event
-> VersionedProjectionCache state m
-> VersionedStreamProjection state event
-> m ()
updateProjectionCache VersionedEventStoreReader m CounterEvent
reader VersionedProjectionCache Counter m
cache (UUID
-> CounterProjection
-> StreamProjection UUID EventVersion Counter CounterEvent
forall state event.
UUID
-> Projection state event -> VersionedStreamProjection state event
versionedStreamProjection UUID
nil CounterProjection
counterProjection)
        VersionedEventStoreReader m CounterEvent
-> VersionedProjectionCache Counter m
-> StreamProjection UUID EventVersion Counter CounterEvent
-> m (StreamProjection UUID EventVersion Counter CounterEvent)
forall (m :: * -> *) event state.
Monad m =>
VersionedEventStoreReader m event
-> VersionedProjectionCache state m
-> VersionedStreamProjection state event
-> m (VersionedStreamProjection state event)
getLatestVersionedProjectionWithCache VersionedEventStoreReader m CounterEvent
reader VersionedProjectionCache Counter m
cache (UUID
-> CounterProjection
-> StreamProjection UUID EventVersion Counter CounterEvent
forall state event.
UUID
-> Projection state event -> VersionedStreamProjection state event
versionedStreamProjection UUID
nil CounterProjection
counterProjection)
      StreamProjection UUID EventVersion Counter CounterEvent -> UUID
forall key position state event.
StreamProjection key position state event -> key
streamProjectionKey StreamProjection UUID EventVersion Counter CounterEvent
snapshot UUID -> UUID -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` UUID
nil
      StreamProjection UUID EventVersion Counter CounterEvent
-> EventVersion
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection UUID EventVersion Counter CounterEvent
snapshot EventVersion -> EventVersion -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` EventVersion
2
      StreamProjection UUID EventVersion Counter CounterEvent -> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection UUID EventVersion Counter CounterEvent
snapshot Counter -> Counter -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Counter
Counter Int
6

newtype GlobalStreamProjectionCacheRunner m
  = GlobalStreamProjectionCacheRunner
      ( forall a.
        ( VersionedEventStoreWriter m CounterEvent ->
          GlobalEventStoreReader m CounterEvent ->
          GlobalStreamProjectionCache Text Counter m ->
          m a
        ) ->
        IO a
      )

globalStreamProjectionCacheSpec ::
  (Monad m) =>
  GlobalStreamProjectionCacheRunner m ->
  Spec
globalStreamProjectionCacheSpec :: forall (m :: * -> *).
Monad m =>
GlobalStreamProjectionCacheRunner m -> Spec
globalStreamProjectionCacheSpec (GlobalStreamProjectionCacheRunner forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m a)
-> IO a
withStoreAndCache) = do
  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when the store is empty" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should be able to store and load simple projections" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      Maybe (SequenceNumber, Counter)
snapshot <- (VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m (Maybe (SequenceNumber, Counter)))
-> IO (Maybe (SequenceNumber, Counter))
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m a)
-> IO a
withStoreAndCache ((VersionedEventStoreWriter m CounterEvent
  -> GlobalEventStoreReader m CounterEvent
  -> GlobalStreamProjectionCache Text Counter m
  -> m (Maybe (SequenceNumber, Counter)))
 -> IO (Maybe (SequenceNumber, Counter)))
-> (VersionedEventStoreWriter m CounterEvent
    -> GlobalEventStoreReader m CounterEvent
    -> GlobalStreamProjectionCache Text Counter m
    -> m (Maybe (SequenceNumber, Counter)))
-> IO (Maybe (SequenceNumber, Counter))
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
_ GlobalEventStoreReader m CounterEvent
_ GlobalStreamProjectionCache Text Counter m
cache -> do
        GlobalStreamProjectionCache Text Counter m
-> Text -> SequenceNumber -> Counter -> m ()
forall key position serialized (m :: * -> *).
ProjectionCache key position serialized m
-> key -> position -> serialized -> m ()
storeProjectionSnapshot GlobalStreamProjectionCache Text Counter m
cache Text
"key" SequenceNumber
4 (Int -> Counter
Counter Int
100)
        GlobalStreamProjectionCache Text Counter m
-> Text -> m (Maybe (SequenceNumber, Counter))
forall key position serialized (m :: * -> *).
ProjectionCache key position serialized m
-> key -> m (Maybe (position, serialized))
loadProjectionSnapshot GlobalStreamProjectionCache Text Counter m
cache Text
"key"
      Maybe (SequenceNumber, Counter)
snapshot Maybe (SequenceNumber, Counter)
-> Maybe (SequenceNumber, Counter) -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` (SequenceNumber, Counter) -> Maybe (SequenceNumber, Counter)
forall a. a -> Maybe a
Just (SequenceNumber
4, Int -> Counter
Counter Int
100)

  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when the store has some events in one stream" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should load from a global stream of events" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot <- (VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m (StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> IO
     (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m a)
-> IO a
withStoreAndCache ((VersionedEventStoreWriter m CounterEvent
  -> GlobalEventStoreReader m CounterEvent
  -> GlobalStreamProjectionCache Text Counter m
  -> m (StreamProjection
          () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
 -> IO
      (StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> (VersionedEventStoreWriter m CounterEvent
    -> GlobalEventStoreReader m CounterEvent
    -> GlobalStreamProjectionCache Text Counter m
    -> m (StreamProjection
            () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> IO
     (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer GlobalEventStoreReader m CounterEvent
globalReader GlobalStreamProjectionCache Text Counter m
cache -> do
        Either (EventWriteError EventVersion) EventVersion
_ <- VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
AnyPosition [Int -> CounterEvent
Added Int
1, Int -> CounterEvent
Added Int
2]
        GlobalEventStoreReader m CounterEvent
-> GlobalStreamProjectionCache Text Counter m
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> Text
-> m (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall (m :: * -> *) event key state.
Monad m =>
GlobalEventStoreReader m event
-> GlobalStreamProjectionCache key state m
-> GlobalStreamProjection state event
-> key
-> m (GlobalStreamProjection state event)
getLatestGlobalProjectionWithCache GlobalEventStoreReader m CounterEvent
globalReader GlobalStreamProjectionCache Text Counter m
cache (Projection Counter (VersionedStreamEvent CounterEvent)
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
forall state event.
Projection state (VersionedStreamEvent event)
-> GlobalStreamProjection state event
globalStreamProjection Projection Counter (VersionedStreamEvent CounterEvent)
counterGlobalProjection) Text
"key"
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> SequenceNumber
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot SequenceNumber -> SequenceNumber -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` SequenceNumber
2
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot Counter -> Counter -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Counter
Counter Int
3

    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should work with updateGlobalProjectionCache" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot <- (VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m (StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> IO
     (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m a)
-> IO a
withStoreAndCache ((VersionedEventStoreWriter m CounterEvent
  -> GlobalEventStoreReader m CounterEvent
  -> GlobalStreamProjectionCache Text Counter m
  -> m (StreamProjection
          () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
 -> IO
      (StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> (VersionedEventStoreWriter m CounterEvent
    -> GlobalEventStoreReader m CounterEvent
    -> GlobalStreamProjectionCache Text Counter m
    -> m (StreamProjection
            () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> IO
     (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer GlobalEventStoreReader m CounterEvent
globalReader GlobalStreamProjectionCache Text Counter m
cache -> do
        Either (EventWriteError EventVersion) EventVersion
_ <- VersionedEventStoreWriter m CounterEvent
-> UUID
-> ExpectedPosition EventVersion
-> [CounterEvent]
-> m (Either (EventWriteError EventVersion) EventVersion)
forall key position (m :: * -> *) event.
EventStoreWriter key position m event
-> key
-> ExpectedPosition position
-> [event]
-> m (Either (EventWriteError position) EventVersion)
storeEvents VersionedEventStoreWriter m CounterEvent
writer UUID
nil ExpectedPosition EventVersion
forall position. ExpectedPosition position
AnyPosition [Int -> CounterEvent
Added Int
1, Int -> CounterEvent
Added Int
2, Int -> CounterEvent
Added Int
3]
        GlobalEventStoreReader m CounterEvent
-> GlobalStreamProjectionCache Text Counter m
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> Text
-> m ()
forall (m :: * -> *) event key state.
Monad m =>
GlobalEventStoreReader m event
-> GlobalStreamProjectionCache key state m
-> GlobalStreamProjection state event
-> key
-> m ()
updateGlobalProjectionCache GlobalEventStoreReader m CounterEvent
globalReader GlobalStreamProjectionCache Text Counter m
cache (Projection Counter (VersionedStreamEvent CounterEvent)
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
forall state event.
Projection state (VersionedStreamEvent event)
-> GlobalStreamProjection state event
globalStreamProjection Projection Counter (VersionedStreamEvent CounterEvent)
counterGlobalProjection) Text
"key"
        GlobalEventStoreReader m CounterEvent
-> GlobalStreamProjectionCache Text Counter m
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> Text
-> m (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall (m :: * -> *) event key state.
Monad m =>
GlobalEventStoreReader m event
-> GlobalStreamProjectionCache key state m
-> GlobalStreamProjection state event
-> key
-> m (GlobalStreamProjection state event)
getLatestGlobalProjectionWithCache GlobalEventStoreReader m CounterEvent
globalReader GlobalStreamProjectionCache Text Counter m
cache (Projection Counter (VersionedStreamEvent CounterEvent)
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
forall state event.
Projection state (VersionedStreamEvent event)
-> GlobalStreamProjection state event
globalStreamProjection Projection Counter (VersionedStreamEvent CounterEvent)
counterGlobalProjection) Text
"key"
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> SequenceNumber
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot SequenceNumber -> SequenceNumber -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` SequenceNumber
3
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot Counter -> Counter -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Counter
Counter Int
6

  String -> Spec -> Spec
forall a. HasCallStack => String -> SpecWith a -> SpecWith a
context String
"when events from multiple UUIDs are inserted" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    String -> IO () -> SpecWith (Arg (IO ()))
forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
it String
"should have the correct cached projection value" (IO () -> SpecWith (Arg (IO ())))
-> IO () -> SpecWith (Arg (IO ()))
forall a b. (a -> b) -> a -> b
$ do
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot <- (VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m (StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> IO
     (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a.
(VersionedEventStoreWriter m CounterEvent
 -> GlobalEventStoreReader m CounterEvent
 -> GlobalStreamProjectionCache Text Counter m
 -> m a)
-> IO a
withStoreAndCache ((VersionedEventStoreWriter m CounterEvent
  -> GlobalEventStoreReader m CounterEvent
  -> GlobalStreamProjectionCache Text Counter m
  -> m (StreamProjection
          () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
 -> IO
      (StreamProjection
         () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> (VersionedEventStoreWriter m CounterEvent
    -> GlobalEventStoreReader m CounterEvent
    -> GlobalStreamProjectionCache Text Counter m
    -> m (StreamProjection
            () SequenceNumber Counter (VersionedStreamEvent CounterEvent)))
-> IO
     (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall a b. (a -> b) -> a -> b
$ \VersionedEventStoreWriter m CounterEvent
writer GlobalEventStoreReader m CounterEvent
globalReader GlobalStreamProjectionCache Text Counter m
cache -> do
        VersionedEventStoreWriter m CounterEvent -> m ()
forall (m :: * -> *).
Monad m =>
VersionedEventStoreWriter m CounterEvent -> m ()
insertExampleEvents VersionedEventStoreWriter m CounterEvent
writer
        GlobalEventStoreReader m CounterEvent
-> GlobalStreamProjectionCache Text Counter m
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> Text
-> m ()
forall (m :: * -> *) event key state.
Monad m =>
GlobalEventStoreReader m event
-> GlobalStreamProjectionCache key state m
-> GlobalStreamProjection state event
-> key
-> m ()
updateGlobalProjectionCache GlobalEventStoreReader m CounterEvent
globalReader GlobalStreamProjectionCache Text Counter m
cache (Projection Counter (VersionedStreamEvent CounterEvent)
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
forall state event.
Projection state (VersionedStreamEvent event)
-> GlobalStreamProjection state event
globalStreamProjection Projection Counter (VersionedStreamEvent CounterEvent)
counterGlobalProjection) Text
"key"
        GlobalEventStoreReader m CounterEvent
-> GlobalStreamProjectionCache Text Counter m
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> Text
-> m (StreamProjection
        () SequenceNumber Counter (VersionedStreamEvent CounterEvent))
forall (m :: * -> *) event key state.
Monad m =>
GlobalEventStoreReader m event
-> GlobalStreamProjectionCache key state m
-> GlobalStreamProjection state event
-> key
-> m (GlobalStreamProjection state event)
getLatestGlobalProjectionWithCache GlobalEventStoreReader m CounterEvent
globalReader GlobalStreamProjectionCache Text Counter m
cache (Projection Counter (VersionedStreamEvent CounterEvent)
-> StreamProjection
     () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
forall state event.
Projection state (VersionedStreamEvent event)
-> GlobalStreamProjection state event
globalStreamProjection Projection Counter (VersionedStreamEvent CounterEvent)
counterGlobalProjection) Text
"key"
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> SequenceNumber
forall key position state event.
StreamProjection key position state event -> position
streamProjectionPosition StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot SequenceNumber -> SequenceNumber -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` SequenceNumber
5
      StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
-> Counter
forall key position state event.
StreamProjection key position state event -> state
streamProjectionState StreamProjection
  () SequenceNumber Counter (VersionedStreamEvent CounterEvent)
snapshot Counter -> Counter -> IO ()
forall a. (HasCallStack, Show a, Eq a) => a -> a -> IO ()
`shouldBe` Int -> Counter
Counter Int
15