packages feed

eventful-test-helpers 0.1.3 → 0.2.0

raw patch · 2 files changed

+168/−158 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Eventful.TestHelpers: GloballyOrderedEventStoreRunner :: (forall a. (EventStore CounterEvent m -> GloballyOrderedEventStore CounterEvent m -> m a) -> IO a) -> GloballyOrderedEventStoreRunner m
- Eventful.TestHelpers: GloballyOrderedProjectionCacheRunner :: (forall a. (EventStore CounterEvent m -> GloballyOrderedEventStore CounterEvent m -> GloballyOrderedProjectionCache Text Counter m -> m a) -> IO a) -> GloballyOrderedProjectionCacheRunner m
- Eventful.TestHelpers: StreamProjectionCacheRunner :: (forall a. (EventStore CounterEvent m -> StreamProjectionCache Counter m -> m a) -> IO a) -> StreamProjectionCacheRunner m
- Eventful.TestHelpers: globallyOrderedProjectionCacheSpec :: (Monad m) => GloballyOrderedProjectionCacheRunner m -> Spec
- Eventful.TestHelpers: newtype GloballyOrderedEventStoreRunner m
- Eventful.TestHelpers: newtype GloballyOrderedProjectionCacheRunner m
- Eventful.TestHelpers: newtype StreamProjectionCacheRunner m
- Eventful.TestHelpers: sequencedEventStoreSpec :: (Monad m) => GloballyOrderedEventStoreRunner m -> Spec
- Eventful.TestHelpers: streamProjectionCacheSpec :: (Monad m) => StreamProjectionCacheRunner m -> Spec
+ Eventful.TestHelpers: GlobalStreamEventStoreRunner :: (forall a. (EventStoreWriter m CounterEvent -> GlobalEventStoreReader m CounterEvent -> m a) -> IO a) -> GlobalStreamEventStoreRunner m
+ Eventful.TestHelpers: GlobalStreamProjectionCacheRunner :: (forall a. (EventStoreWriter m CounterEvent -> GlobalEventStoreReader m CounterEvent -> GlobalStreamProjectionCache Text Counter m -> m a) -> IO a) -> GlobalStreamProjectionCacheRunner m
+ Eventful.TestHelpers: VersionedProjectionCacheRunner :: (forall a. (EventStoreWriter m CounterEvent -> VersionedEventStoreReader m CounterEvent -> VersionedProjectionCache Counter m -> m a) -> IO a) -> VersionedProjectionCacheRunner m
+ Eventful.TestHelpers: globalStreamEventStoreSpec :: (Monad m) => GlobalStreamEventStoreRunner m -> Spec
+ Eventful.TestHelpers: globalStreamProjectionCacheSpec :: (Monad m) => GlobalStreamProjectionCacheRunner m -> Spec
+ Eventful.TestHelpers: newtype GlobalStreamEventStoreRunner m
+ Eventful.TestHelpers: newtype GlobalStreamProjectionCacheRunner m
+ Eventful.TestHelpers: newtype VersionedProjectionCacheRunner m
+ Eventful.TestHelpers: versionedProjectionCacheSpec :: (Monad m) => VersionedProjectionCacheRunner m -> Spec
- Eventful.TestHelpers: EventStoreRunner :: (forall a. (EventStore CounterEvent m -> m a) -> IO a) -> EventStoreRunner m
+ Eventful.TestHelpers: EventStoreRunner :: (forall a. (EventStoreWriter m CounterEvent -> VersionedEventStoreReader m CounterEvent -> m a) -> IO a) -> EventStoreRunner m

Files

eventful-test-helpers.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack  name:           eventful-test-helpers-version:        0.1.3+version:        0.2.0 synopsis:       Common module used for eventful tests description:    Common module used for eventful tests category:       Database,Eventsourcing
src/Eventful/TestHelpers.hs view
@@ -14,13 +14,13 @@   , CounterEvent (..)   , CounterCommand (..)   , EventStoreRunner (..)-  , GloballyOrderedEventStoreRunner (..)+  , GlobalStreamEventStoreRunner (..)   , eventStoreSpec-  , sequencedEventStoreSpec-  , StreamProjectionCacheRunner (..)-  , streamProjectionCacheSpec-  , GloballyOrderedProjectionCacheRunner (..)-  , globallyOrderedProjectionCacheSpec+  , globalStreamEventStoreSpec+  , VersionedProjectionCacheRunner (..)+  , versionedProjectionCacheSpec+  , GlobalStreamProjectionCacheRunner (..)+  , globalStreamProjectionCacheSpec   , Text   , module X   ) where@@ -56,11 +56,11 @@   (Counter 0)   (\(Counter k) (Added x) -> Counter (k + x)) -counterGlobalProjection :: Projection Counter (GloballyOrderedEvent CounterEvent)+counterGlobalProjection :: Projection Counter (VersionedStreamEvent CounterEvent) counterGlobalProjection =   Projection   (Counter 0)-  (\(Counter k) (GloballyOrderedEvent _ _ _ (Added x)) -> Counter (k + x))+  (\(Counter k) (StreamEvent _ _ (Added x)) -> Counter (k + x))  data CounterCommand   = Increment@@ -92,9 +92,7 @@ -- Test harness for stores  newtype EventStoreRunner m =-  EventStoreRunner (forall a. (EventStore CounterEvent m -> m a) -> IO a)-newtype GloballyOrderedEventStoreRunner m =-  GloballyOrderedEventStoreRunner (forall a. (EventStore CounterEvent m -> GloballyOrderedEventStore CounterEvent m -> m a) -> IO a)+  EventStoreRunner (forall a. (EventStoreWriter m CounterEvent -> VersionedEventStoreReader m CounterEvent -> m a) -> IO a)  eventStoreSpec   :: (Monad m)@@ -102,178 +100,184 @@   -> Spec eventStoreSpec (EventStoreRunner withStore) = do   let-    withStoreExampleEvents action = withStore $ \store -> do-      _ <- insertExampleEvents store-      action store--  context "when the event store is empty" $ do--    it "should return versions of -1 for a UUID" $ do-      withStore (\store -> getLatestVersion store nil) `shouldReturn` (-1)+    withStoreExampleEvents action = withStore $ \writer reader -> do+      _ <- insertExampleEvents writer+      action writer reader    context "when a few events are inserted" $ do     let       sampleEvents = [Added 1, Added 4, Added (-3), Added 5]-      withStore' action = withStore $ \store -> do-        _ <- storeEvents store NoStream nil sampleEvents-        action store+      withStore' action = withStore $ \writer reader -> do+        _ <- storeEvents writer NoStream nil sampleEvents+        action writer reader      it "should return events" $ do-      events' <- withStore' $ \store -> getEvents store nil allEvents-      (storedEventEvent <$> events') `shouldBe` sampleEvents+      events' <- withStore' $ \_ reader -> getEvents reader (allEvents nil)+      (streamEventEvent <$> events') `shouldBe` sampleEvents      it "should return correct event versions" $ do-      (latestVersion, events) <- withStore' $ \store ->-        (,) <$>-          getLatestVersion store nil <*>-          getEvents store nil allEvents-      latestVersion `shouldBe` 3-      (storedEventVersion <$> events) `shouldBe` [0, 1, 2, 3]+      events <- withStore' $ \_ reader -> getEvents reader (allEvents nil)+      (streamEventPosition <$> events) `shouldBe` [0, 1, 2, 3]      it "should return correct events with queries" $ do-      (firstEvents, middleEvents, laterEvents, maxEvents) <- withStore' $ \store ->+      (firstEvents, middleEvents, laterEvents, maxEvents) <- withStore' $ \_ reader ->         (,,,) <$>-          getEvents store nil (eventsUntil 1) <*>-          getEvents store nil (eventsStartingAtUntil 1 2) <*>-          getEvents store nil (eventsStartingAt 2) <*>-          getEvents store nil (eventsStartingAtTakeLimit 0 2)-      (storedEventEvent <$> firstEvents) `shouldBe` take 2 sampleEvents-      (storedEventEvent <$> middleEvents) `shouldBe` take 2 (drop 1 sampleEvents)-      (storedEventEvent <$> laterEvents) `shouldBe` drop 2 sampleEvents-      (storedEventEvent <$> maxEvents) `shouldBe` take 2 sampleEvents+          getEvents reader (eventsUntil nil 1) <*>+          getEvents reader (eventsStartingAtUntil nil 1 2) <*>+          getEvents reader (eventsStartingAt nil 2) <*>+          getEvents reader (eventsStartingAtTakeLimit nil 0 2)+      (streamEventEvent <$> firstEvents) `shouldBe` take 2 sampleEvents+      (streamEventEvent <$> middleEvents) `shouldBe` take 2 (drop 1 sampleEvents)+      (streamEventEvent <$> laterEvents) `shouldBe` drop 2 sampleEvents+      (streamEventEvent <$> maxEvents) `shouldBe` take 2 sampleEvents      it "should return the latest projection" $ do-      projection <- withStore' $ \store ->-        getLatestProjection store (streamProjection counterProjection nil)+      projection <- withStore' $ \_ reader ->+        getLatestStreamProjection reader (versionedStreamProjection nil counterProjection)       streamProjectionState projection `shouldBe` Counter 7-      streamProjectionVersion projection `shouldBe` 3-      streamProjectionUuid projection `shouldBe` nil+      streamProjectionPosition projection `shouldBe` 3+      streamProjectionKey projection `shouldBe` nil      it "should return the latest projection with some starting StreamProjection" $ do-      projection <- withStore' $ \store -> do-        initialEvents <- getEvents store nil (eventsUntil 1)-        let initialProjection = latestProjection counterProjection (storedEventEvent <$> initialEvents)-        getLatestProjection store (StreamProjection counterProjection nil 1 initialProjection)+      projection <- withStore' $ \_ reader -> do+        initialEvents <- getEvents reader (eventsUntil nil 1)+        let initialProjection = latestProjection counterProjection (streamEventEvent <$> initialEvents)+        getLatestStreamProjection reader (StreamProjection nil 1 counterProjection initialProjection)       streamProjectionState projection `shouldBe` Counter 7-      streamProjectionVersion projection `shouldBe` 3-      streamProjectionUuid projection `shouldBe` nil+      streamProjectionPosition projection `shouldBe` 3+      streamProjectionKey projection `shouldBe` nil    context "when events from multiple UUIDs are inserted" $ do      it "should have the correct events for each aggregate" $ do-      (events1, events2) <- withStoreExampleEvents $ \store ->-        (,) <$> getEvents store uuid1 allEvents <*> getEvents store uuid2 allEvents-      (storedEventEvent <$> events1) `shouldBe` Added <$> [1, 4]-      (storedEventEvent <$> events2) `shouldBe` Added <$> [2, 3, 5]-      (storedEventProjectionId <$> events1) `shouldBe` [uuid1, uuid1]-      (storedEventProjectionId <$> events2) `shouldBe` [uuid2, uuid2, uuid2]-      (storedEventVersion <$> events1) `shouldBe` [0, 1]-      (storedEventVersion <$> events2) `shouldBe` [0, 1, 2]+      (events1, events2) <- withStoreExampleEvents $ \_ reader ->+        (,) <$> getEvents reader (allEvents uuid1) <*> getEvents reader (allEvents uuid2)+      (streamEventEvent <$> events1) `shouldBe` Added <$> [1, 4]+      (streamEventEvent <$> events2) `shouldBe` Added <$> [2, 3, 5]+      (streamEventKey <$> events1) `shouldBe` [uuid1, uuid1]+      (streamEventKey <$> events2) `shouldBe` [uuid2, uuid2, uuid2]+      (streamEventPosition <$> events1) `shouldBe` [0, 1]+      (streamEventPosition <$> events2) `shouldBe` [0, 1, 2]      it "should return correct event versions" $ do-      (latestVersion1, latestVersion2, events1, events2) <- withStoreExampleEvents $ \store ->-        (,,,) <$>-          getLatestVersion store uuid1 <*>-          getLatestVersion store uuid2 <*>-          getEvents store uuid1 allEvents <*>-          getEvents store uuid2 allEvents-      latestVersion1 `shouldBe` 1-      latestVersion2 `shouldBe` 2-      storedEventEvent <$> events1 `shouldBe` [Added 1, Added 4]-      storedEventEvent <$> events2 `shouldBe` [Added 2, Added 3, Added 5]+      (events1, events2) <- withStoreExampleEvents $ \_ reader ->+        (,) <$>+          getEvents reader (allEvents uuid1) <*>+          getEvents reader (allEvents uuid2)+      streamEventEvent <$> events1 `shouldBe` [Added 1, Added 4]+      streamEventEvent <$> events2 `shouldBe` [Added 2, Added 3, Added 5]      it "should return correct events with queries" $ do-      (firstEvents, middleEvents, laterEvents, maxEvents) <- withStoreExampleEvents $ \store ->+      (firstEvents, middleEvents, laterEvents, maxEvents) <- withStoreExampleEvents $ \_ reader ->         (,,,) <$>-          getEvents store uuid1 (eventsUntil 1) <*>-          getEvents store uuid2 (eventsStartingAtUntil 1 2) <*>-          getEvents store uuid2 (eventsStartingAt 2) <*>-          getEvents store uuid1 (eventsStartingAtTakeLimit 1 1)-      (storedEventEvent <$> firstEvents) `shouldBe` [Added 1, Added 4]-      (storedEventEvent <$> middleEvents) `shouldBe` [Added 3, Added 5]-      (storedEventEvent <$> laterEvents) `shouldBe` [Added 5]-      (storedEventEvent <$> maxEvents) `shouldBe` [Added 4]+          getEvents reader (eventsUntil uuid1 1) <*>+          getEvents reader (eventsStartingAtUntil uuid2 1 2) <*>+          getEvents reader (eventsStartingAt uuid2 2) <*>+          getEvents reader (eventsStartingAtTakeLimit uuid1 1 1)+      (streamEventEvent <$> firstEvents) `shouldBe` [Added 1, Added 4]+      (streamEventEvent <$> middleEvents) `shouldBe` [Added 3, Added 5]+      (streamEventEvent <$> laterEvents) `shouldBe` [Added 5]+      (streamEventEvent <$> maxEvents) `shouldBe` [Added 4]      it "should produce the correct projections" $ do-      (proj1, proj2) <- withStoreExampleEvents $ \store ->+      (proj1, proj2) <- withStoreExampleEvents $ \_ reader ->         (,) <$>-          getLatestProjection store (streamProjection counterProjection uuid1) <*>-          getLatestProjection store (streamProjection counterProjection uuid2)-      (streamProjectionState proj1, streamProjectionVersion proj1) `shouldBe` (Counter 5, 1)-      (streamProjectionState proj2, streamProjectionVersion proj2) `shouldBe` (Counter 10, 2)+          getLatestStreamProjection reader (versionedStreamProjection uuid1 counterProjection) <*>+          getLatestStreamProjection reader (versionedStreamProjection uuid2 counterProjection)+      (streamProjectionState proj1, streamProjectionPosition proj1) `shouldBe` (Counter 5, 1)+      (streamProjectionState proj2, streamProjectionPosition proj2) `shouldBe` (Counter 10, 2)    describe "can handle event storage errors" $ do      it "rejects some writes when event store isn't created" $ do-      (err1, err2) <- withStore $ \store -> do+      (err1, err2) <- withStore $ \writer _ ->         (,) <$>-          storeEvents store StreamExists nil [Added 1] <*>-          storeEvents store (ExactVersion 0) nil [Added 1]+          storeEvents writer StreamExists nil [Added 1] <*>+          storeEvents writer (ExactVersion 0) nil [Added 1]       err1 `shouldBe` Just (EventStreamNotAtExpectedVersion (-1))       err2 `shouldBe` Just (EventStreamNotAtExpectedVersion (-1))      it "should be able to store events starting with an empty stream" $ do-      withStore (\store -> storeEvents store NoStream nil [Added 1]) `shouldReturn` Nothing+      withStore (\writer _ -> storeEvents writer NoStream nil [Added 1]) `shouldReturn` Nothing      it "should reject storing events sometimes with a stream" $ do-      (err1, err2, err3) <- withStore $ \store ->+      (err1, err2, err3) <- withStore $ \writer _ ->         (,,) <$>-          storeEvents store NoStream nil [Added 1] <*>-          storeEvents store NoStream nil [Added 1] <*>-          storeEvents store (ExactVersion 1) nil [Added 1]+          storeEvents writer NoStream nil [Added 1] <*>+          storeEvents writer NoStream nil [Added 1] <*>+          storeEvents writer (ExactVersion 1) nil [Added 1]       err1 `shouldBe` Nothing       err2 `shouldBe` Just (EventStreamNotAtExpectedVersion 0)       err3 `shouldBe` Just (EventStreamNotAtExpectedVersion 0)      it "should accepts storing events sometimes with a stream" $ do-      errors <- withStore $ \store ->+      errors <- withStore $ \writer _ ->         sequence-          [ storeEvents store NoStream nil [Added 1]-          , storeEvents store AnyVersion nil [Added 1]-          , storeEvents store (ExactVersion 1) nil [Added 1]-          , storeEvents store StreamExists nil [Added 1]+          [ storeEvents writer NoStream nil [Added 1]+          , storeEvents writer AnyVersion nil [Added 1]+          , storeEvents writer (ExactVersion 1) nil [Added 1]+          , storeEvents writer StreamExists nil [Added 1]           ]       errors `shouldBe` [Nothing, Nothing, Nothing, Nothing] -sequencedEventStoreSpec+newtype GlobalStreamEventStoreRunner m =+  GlobalStreamEventStoreRunner+  (forall a. (EventStoreWriter m CounterEvent -> GlobalEventStoreReader m CounterEvent -> m a) -> IO a)++globalStreamEventStoreSpec   :: (Monad m)-  => GloballyOrderedEventStoreRunner m+  => GlobalStreamEventStoreRunner m   -> Spec-sequencedEventStoreSpec (GloballyOrderedEventStoreRunner withStore) = do+globalStreamEventStoreSpec (GlobalStreamEventStoreRunner withStore) = do   context "when the event store is empty" $ do      it "shouldn't have any events" $ do-      events <- withStore (\_ globalStore -> getSequencedEvents globalStore allEvents)+      events <- withStore (\_ globalReader -> getEvents globalReader (allEvents ()))       length events `shouldBe` 0    context "when events from multiple UUIDs are inserted" $ do      it "should have the correct events in global order" $ do-      events <- withStore $ \store globalStore -> do-        insertExampleEvents store-        getSequencedEvents globalStore allEvents-      (globallyOrderedEventEvent <$> events) `shouldBe` Added <$> [1..5]-      (globallyOrderedEventProjectionId <$> events) `shouldBe` [uuid1, uuid2, uuid2, uuid1, uuid2]-      (globallyOrderedEventVersion <$> events) `shouldBe` [0, 0, 1, 1, 2]-      (globallyOrderedEventSequenceNumber <$> events) `shouldBe` [1..5]+      events <- withStore $ \writer globalReader -> do+        insertExampleEvents writer+        getEvents globalReader (allEvents ())+      (streamEventEvent . streamEventEvent <$> events) `shouldBe` Added <$> [1..5]+      (streamEventKey . streamEventEvent <$> events) `shouldBe` [uuid1, uuid2, uuid2, uuid1, uuid2]+      (streamEventPosition . streamEventEvent <$> events) `shouldBe` [0, 0, 1, 1, 2]+      (streamEventPosition <$> events) `shouldBe` [1..5] +    it "should work with global projections" $ do+      (proj1, proj2) <- withStore $ \writer globalReader -> do+        insertExampleEvents writer+        p1 <- getLatestStreamProjection globalReader (globalStreamProjection counterGlobalProjection)+        _ <- storeEvents writer AnyVersion uuid1 [Added 10, Added 20]+        p2 <- getLatestStreamProjection globalReader p1+        return (p1, p2)++      streamProjectionPosition proj1 `shouldBe` 5+      streamProjectionPosition proj2 `shouldBe` 7+     it "should handle queries" $ do-      (firstEvents, middleEvents, laterEvents, maxEvents) <- withStore $ \store globalStore -> do-        insertExampleEvents store+      (firstEvents, middleEvents, laterEvents, maxEvents) <- withStore $ \writer globalReader -> do+        insertExampleEvents writer         (,,,) <$>-          getSequencedEvents globalStore (eventsUntil 2) <*>-          getSequencedEvents globalStore (eventsStartingAtUntil 2 3) <*>-          getSequencedEvents globalStore (eventsStartingAt 3) <*>-          getSequencedEvents globalStore (eventsStartingAtTakeLimit 2 3)+          getEvents globalReader (eventsUntil () 2) <*>+          getEvents globalReader (eventsStartingAtUntil () 2 3) <*>+          getEvents globalReader (eventsStartingAt () 3) <*>+          getEvents globalReader (eventsStartingAtTakeLimit () 2 3) -      (globallyOrderedEventEvent <$> firstEvents) `shouldBe` Added <$> [1..2]-      (globallyOrderedEventEvent <$> middleEvents) `shouldBe` Added <$> [2..3]-      (globallyOrderedEventEvent <$> laterEvents) `shouldBe` Added <$> [3..5]-      (globallyOrderedEventEvent <$> maxEvents) `shouldBe` Added <$> [2..4]+      (streamEventEvent . streamEventEvent <$> firstEvents) `shouldBe` Added <$> [1..2]+      (streamEventPosition <$> firstEvents) `shouldBe` [1..2]+      (streamEventEvent . streamEventEvent <$> middleEvents) `shouldBe` Added <$> [2..3]+      (streamEventPosition <$> middleEvents) `shouldBe` [2..3]+      (streamEventEvent . streamEventEvent <$> laterEvents) `shouldBe` Added <$> [3..5]+      (streamEventPosition <$> laterEvents) `shouldBe` [3..5]+      (streamEventEvent . streamEventEvent <$> maxEvents) `shouldBe` Added <$> [2..4]+      (streamEventPosition <$> maxEvents) `shouldBe` [2..4]  insertExampleEvents   :: (Monad m)-  => EventStore CounterEvent m+  => EventStoreWriter m CounterEvent   -> m () insertExampleEvents store = do   void $ storeEvents store NoStream uuid1 [Added 1]@@ -287,18 +291,24 @@ uuid2 :: UUID uuid2 = uuidFromInteger 2 -newtype StreamProjectionCacheRunner m =-  StreamProjectionCacheRunner (forall a. (EventStore CounterEvent m -> StreamProjectionCache Counter m -> m a) -> IO a)+newtype VersionedProjectionCacheRunner m =+  VersionedProjectionCacheRunner+  (forall a.+   (  EventStoreWriter m CounterEvent+   -> VersionedEventStoreReader m CounterEvent+   -> VersionedProjectionCache Counter m -> m a)+   -> IO a+  ) -streamProjectionCacheSpec+versionedProjectionCacheSpec   :: (Monad m)-  => StreamProjectionCacheRunner m+  => VersionedProjectionCacheRunner m   -> Spec-streamProjectionCacheSpec (StreamProjectionCacheRunner withStoreAndCache) = do+versionedProjectionCacheSpec (VersionedProjectionCacheRunner withStoreAndCache) = do   context "when the store is empty" $ do      it "should be able to store and load simple projections" $ do-      snapshot <- withStoreAndCache $ \_ cache -> do+      snapshot <- withStoreAndCache $ \_ _ cache -> do         storeProjectionSnapshot cache nil 4 (Counter 100)         loadProjectionSnapshot cache nil       snapshot `shouldBe` Just (4, Counter 100)@@ -306,34 +316,34 @@   context "when the store has some events in one stream" $ do      it "should load from a stream of events" $ do-      snapshot <- withStoreAndCache $ \store cache -> do-        _ <- storeEvents store AnyVersion nil [Added 1, Added 2]-        getLatestProjectionWithCache store cache (streamProjection counterProjection nil)-      streamProjectionVersion snapshot `shouldBe` 1+      snapshot <- withStoreAndCache $ \writer reader cache -> do+        _ <- storeEvents writer AnyVersion nil [Added 1, Added 2]+        getLatestVersionedProjectionWithCache reader cache (versionedStreamProjection nil counterProjection)+      streamProjectionPosition snapshot `shouldBe` 1       streamProjectionState snapshot `shouldBe` Counter 3      it "should work with updateProjectionCache" $ do-      snapshot <- withStoreAndCache $ \store cache -> do-        _ <- storeEvents store AnyVersion nil [Added 1, Added 2, Added 3]-        updateProjectionCache store cache (streamProjection counterProjection nil)-        getLatestProjectionWithCache store cache (streamProjection counterProjection nil)-      streamProjectionUuid snapshot `shouldBe` nil-      streamProjectionVersion snapshot `shouldBe` 2+      snapshot <- withStoreAndCache $ \writer reader cache -> do+        _ <- storeEvents writer AnyVersion nil [Added 1, Added 2, Added 3]+        updateProjectionCache reader cache (versionedStreamProjection nil counterProjection)+        getLatestVersionedProjectionWithCache reader cache (versionedStreamProjection nil counterProjection)+      streamProjectionKey snapshot `shouldBe` nil+      streamProjectionPosition snapshot `shouldBe` 2       streamProjectionState snapshot `shouldBe` Counter 6 -newtype GloballyOrderedProjectionCacheRunner m =-  GloballyOrderedProjectionCacheRunner+newtype GlobalStreamProjectionCacheRunner m =+  GlobalStreamProjectionCacheRunner   (forall a.-    ( EventStore CounterEvent m-    -> GloballyOrderedEventStore CounterEvent m-    -> GloballyOrderedProjectionCache Text Counter m -> m a+    (  EventStoreWriter m CounterEvent+    -> GlobalEventStoreReader m CounterEvent+    -> GlobalStreamProjectionCache Text Counter m -> m a     ) -> IO a) -globallyOrderedProjectionCacheSpec+globalStreamProjectionCacheSpec   :: (Monad m)-  => GloballyOrderedProjectionCacheRunner m+  => GlobalStreamProjectionCacheRunner m   -> Spec-globallyOrderedProjectionCacheSpec (GloballyOrderedProjectionCacheRunner withStoreAndCache) = do+globalStreamProjectionCacheSpec (GlobalStreamProjectionCacheRunner withStoreAndCache) = do   context "when the store is empty" $ do      it "should be able to store and load simple projections" $ do@@ -345,26 +355,26 @@   context "when the store has some events in one stream" $ do      it "should load from a global stream of events" $ do-      snapshot <- withStoreAndCache $ \store globalStore cache -> do-        _ <- storeEvents store AnyVersion nil [Added 1, Added 2]-        getLatestGlobalProjectionWithCache globalStore cache (globallyOrderedProjection counterGlobalProjection) "key"-      globallyOrderedProjectionSequenceNumber snapshot `shouldBe` 2-      globallyOrderedProjectionState snapshot `shouldBe` Counter 3+      snapshot <- withStoreAndCache $ \writer globalReader cache -> do+        _ <- storeEvents writer AnyVersion nil [Added 1, Added 2]+        getLatestGlobalProjectionWithCache globalReader cache (globalStreamProjection counterGlobalProjection) "key"+      streamProjectionPosition snapshot `shouldBe` 2+      streamProjectionState snapshot `shouldBe` Counter 3      it "should work with updateGlobalProjectionCache" $ do-      snapshot <- withStoreAndCache $ \store globalStore cache -> do-        _ <- storeEvents store AnyVersion nil [Added 1, Added 2, Added 3]-        updateGlobalProjectionCache globalStore cache (globallyOrderedProjection counterGlobalProjection) "key"-        getLatestGlobalProjectionWithCache globalStore cache (globallyOrderedProjection counterGlobalProjection) "key"-      globallyOrderedProjectionSequenceNumber snapshot `shouldBe` 3-      globallyOrderedProjectionState snapshot `shouldBe` Counter 6+      snapshot <- withStoreAndCache $ \writer globalReader cache -> do+        _ <- storeEvents writer AnyVersion nil [Added 1, Added 2, Added 3]+        updateGlobalProjectionCache globalReader cache (globalStreamProjection counterGlobalProjection) "key"+        getLatestGlobalProjectionWithCache globalReader cache (globalStreamProjection counterGlobalProjection) "key"+      streamProjectionPosition snapshot `shouldBe` 3+      streamProjectionState snapshot `shouldBe` Counter 6    context "when events from multiple UUIDs are inserted" $ do      it "should have the correct cached projection value" $ do-      snapshot <- withStoreAndCache $ \store globalStore cache -> do-        insertExampleEvents store-        updateGlobalProjectionCache globalStore cache (globallyOrderedProjection counterGlobalProjection) "key"-        getLatestGlobalProjectionWithCache globalStore cache (globallyOrderedProjection counterGlobalProjection) "key"-      globallyOrderedProjectionSequenceNumber snapshot `shouldBe` 5-      globallyOrderedProjectionState snapshot `shouldBe` Counter 15+      snapshot <- withStoreAndCache $ \writer globalReader cache -> do+        insertExampleEvents writer+        updateGlobalProjectionCache globalReader cache (globalStreamProjection counterGlobalProjection) "key"+        getLatestGlobalProjectionWithCache globalReader cache (globalStreamProjection counterGlobalProjection) "key"+      streamProjectionPosition snapshot `shouldBe` 5+      streamProjectionState snapshot `shouldBe` Counter 15