packages feed

eventstore 0.3.0.0 → 0.3.1.0

raw patch · 10 files changed

+240/−66 lines, 10 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Database.EventStore: Catchup :: Text -> Chan (Either CatchupError ResolvedEvent) -> IO () -> Catchup
+ Database.EventStore: CatchupStreamDeleted :: Text -> CatchupError
+ Database.EventStore: CatchupStreamDisappeared :: Text -> CatchupError
+ Database.EventStore: CatchupSubscriptionDropReason :: Text -> DropReason -> CatchupError
+ Database.EventStore: CatchupUnexpectedStreamStatus :: Text -> ReadStreamResult -> CatchupError
+ Database.EventStore: catchupChan :: Catchup -> Chan (Either CatchupError ResolvedEvent)
+ Database.EventStore: catchupStream :: Catchup -> Text
+ Database.EventStore: catchupUnsubscribe :: Catchup -> IO ()
+ Database.EventStore: data Catchup
+ Database.EventStore: data CatchupError
+ Database.EventStore: subscribeFrom :: Connection -> Text -> Bool -> Maybe Int32 -> Maybe Int32 -> IO Catchup

Files

Database/EventStore.hs view
@@ -20,6 +20,8 @@     , Port     , Settings(..)     , Subscription(..)+    , Catchup(..)+    , CatchupError(..)     , credentials       -- * Result     , AllEventsSlice(..)@@ -56,6 +58,7 @@     , shutdown     , transactionStart     , subscribe+    , subscribeFrom       -- * Transaction     , Transaction     , transactionCommit@@ -75,6 +78,7 @@ import Data.Text  --------------------------------------------------------------------------------+import Database.EventStore.Catchup import Database.EventStore.Internal.Processor import Database.EventStore.Internal.Types import Database.EventStore.Internal.Operation.DeleteStreamOperation@@ -285,6 +289,21 @@                             stream_id                             res_lnk_tos     async $ readMVar tmp++--------------------------------------------------------------------------------+subscribeFrom :: Connection+              -> Text+              -> Bool+              -> Maybe Int32+              -> Maybe Int32+              -> IO Catchup+subscribeFrom conn stream_id res_lnk_tos last_chk_pt batch_m = do+    catchStart evts_fwd get_sub stream_id batch_m last_chk_pt+  where+    evts_fwd cur_num batch_size =+        readStreamEventsForward conn stream_id cur_num batch_size res_lnk_tos++    get_sub = subscribe conn stream_id res_lnk_tos  -------------------------------------------------------------------------------- createAsync :: IO (Async a, MVar (OperationExceptional a))
+ Database/EventStore/Catchup.hs view
@@ -0,0 +1,156 @@+{-# LANGUAGE DeriveDataTypeable #-}+--------------------------------------------------------------------------------+-- |+-- Module : Database.EventStore.Catchup+-- Copyright : (C) 2014 Yorick Laupa+-- License : (see the file LICENSE)+--+-- Maintainer : Yorick Laupa <yo.eight@gmail.com>+-- Stability : provisional+-- Portability : non-portable+--+--------------------------------------------------------------------------------+module Database.EventStore.Catchup+    ( Catchup(..)+    , CatchupError(..)+    , catchStart+    ) where++--------------------------------------------------------------------------------+import Control.Concurrent+import Control.Exception+import Control.Monad+import Data.Foldable (traverse_)+import Data.Int+import Data.Maybe+import Data.Typeable++--------------------------------------------------------------------------------+import Control.Concurrent.Async+import Data.Text++--------------------------------------------------------------------------------+import Database.EventStore.Internal.Manager.Subscription+import Database.EventStore.Internal.Operation.ReadStreamEventsOperation+import Database.EventStore.Internal.Types++--------------------------------------------------------------------------------+data CatchupError+    = CatchupStreamDisappeared Text+    | CatchupStreamDeleted Text+    | CatchupUnexpectedStreamStatus Text ReadStreamResult+    | CatchupSubscriptionDropReason Text DropReason+    deriving (Show, Typeable)++--------------------------------------------------------------------------------+instance Exception CatchupError++--------------------------------------------------------------------------------+data Catchup+    = Catchup+      { catchupStream      :: Text+      , catchupChan        :: Chan (Either CatchupError ResolvedEvent)+      , catchupUnsubscribe :: IO ()+      }++--------------------------------------------------------------------------------+defaultBatchSize :: Int32+defaultBatchSize = 500++--------------------------------------------------------------------------------+secs :: Int+secs = 1000000++--------------------------------------------------------------------------------+catchStart :: (Int32 -> Int32 -> IO (Async StreamEventsSlice))+           -> IO (Async Subscription)+           -> Text+           -> Maybe Int32+           -> Maybe Int32+           -> IO Catchup+catchStart evt_fwd get_sub stream_id batch_size_m last_m = do+    chan <- newChan+    var  <- newEmptyMVar+    let batch_size   = fromMaybe defaultBatchSize batch_size_m+        nxt_read_evt = fromMaybe 0 last_m++    as <- async $ do+        res_m <- readEventsTill evt_fwd+                                (writeChan chan)+                                stream_id+                                nxt_read_evt+                                batch_size+                                last_m+        case res_m of+            Just e -> throwIO e+            _      -> return ()+        action <- get_sub+        sub    <- wait action+        putMVar var sub+        forever $ do+            evt_e <- readChan $ subChan sub+            case evt_e of+                Right evt -> writeChan chan (Right evt)+                Left r    -> do+                    let e = CatchupSubscriptionDropReason stream_id r++                    writeChan chan (Left e)+                    throwIO e++    let catchup = Catchup+                  { catchupStream      = stream_id+                  , catchupChan        = chan+                  , catchupUnsubscribe = do+                      cancel as+                      sub_m <- tryTakeMVar var+                      traverse_ subUnsubscribe sub_m+                  }++    return catchup++--------------------------------------------------------------------------------+readEventsTill :: (Int32 -> Int32 -> IO (Async StreamEventsSlice))+               -> (Either CatchupError ResolvedEvent -> IO ())+               -> Text+               -> Int32+               -> Int32+               -> Maybe Int32+               -> IO (Maybe CatchupError)+readEventsTill evts_fwd proc_evt stream_id start batch_size last_m =+    loop False start+  where+    loop done cur_evt_num+        | done      = threadDelay (1 * secs) >> return Nothing+        | otherwise = do+              action <- evts_fwd cur_evt_num batch_size+              slice  <- wait action+              case streamEventsSliceResult slice of+                  RS_SUCCESS -> do+                      let nxt    = streamEventsSliceNext slice+                          eos    = streamEventsSliceIsEOS slice+                          n_done = maybe eos (< nxt) last_m+                          evts   = streamEventsSliceEvents slice++                      traverse_ (proc_evt . Right) evts+                      loop n_done nxt+                  RS_NO_STREAM ->+                      if desappeared+                      then reportError desappearError+                      else loop True cur_evt_num+                  RS_STREAM_DELETED -> reportError deletedError+                  s -> reportError $ unexpectedError s++    desappeared =+        case last_m of+            Just i -> i /= (-1)+            _      -> False++    desappearError = CatchupStreamDisappeared stream_id++    deletedError = CatchupStreamDeleted stream_id++    unexpectedError s = CatchupUnexpectedStreamStatus stream_id s++    reportError e = do+        proc_evt $ Left e+        return $ Just e
Database/EventStore/Internal/Manager/Subscription.hs view
@@ -23,7 +23,6 @@  -------------------------------------------------------------------------------- import           Control.Concurrent-import           Control.Monad import           Control.Monad.Fix import           Data.ByteString (ByteString) import           Data.Int
Database/EventStore/Internal/Operation/DeleteStreamOperation.hs view
@@ -31,10 +31,10 @@ -------------------------------------------------------------------------------- data DeleteStream     = DeleteStream-      { deleteStreamId              :: Required 1 (Value Text)-      , deleteStreamExpectedVersion :: Required 2 (Value Int32)-      , deleteStreamRequireMaster   :: Required 3 (Value Bool)-      , deleteStreamHardDelete      :: Optional 4 (Value Bool)+      { _deleteStreamId              :: Required 1 (Value Text)+      , _deleteStreamExpectedVersion :: Required 2 (Value Int32)+      , _deleteStreamRequireMaster   :: Required 3 (Value Bool)+      , _deleteStreamHardDelete      :: Optional 4 (Value Bool)       }     deriving (Generic, Show) @@ -49,19 +49,19 @@                 -> DeleteStream newDeleteStream stream_id exp_ver req_master hard_delete =     DeleteStream-    { deleteStreamId              = putField stream_id-    , deleteStreamExpectedVersion = putField exp_ver-    , deleteStreamRequireMaster   = putField req_master-    , deleteStreamHardDelete      = putField hard_delete+    { _deleteStreamId              = putField stream_id+    , _deleteStreamExpectedVersion = putField exp_ver+    , _deleteStreamRequireMaster   = putField req_master+    , _deleteStreamHardDelete      = putField hard_delete     }  -------------------------------------------------------------------------------- data DeleteStreamCompleted     = DeleteStreamCompleted-      { deleteCompletedResult          :: Required 1 (Enumeration OpResult)-      , deleteCompletedMessage         :: Optional 2 (Value Text)-      , deleteCompletedPreparePosition :: Optional 3 (Value Int64)-      , deleteCompletedCommitPosition  :: Optional 4 (Value Int64)+      { _deleteCompletedResult          :: Required 1 (Enumeration OpResult)+      , _deleteCompletedMessage         :: Optional 2 (Value Text)+      , _deleteCompletedPreparePosition :: Optional 3 (Value Int64)+      , _deleteCompletedCommitPosition  :: Optional 4 (Value Int64)       }     deriving (Generic, Show) @@ -100,7 +100,7 @@         -> ExpectedVersion         -> DeleteStreamCompleted         -> IO Decision-inspect mvar stream exp_ver dsc = go (getField $ deleteCompletedResult dsc)+inspect mvar stream exp_ver dsc = go (getField $ _deleteCompletedResult dsc)   where     go OP_SUCCESS                = succeed mvar dsc     go OP_PREPARE_TIMEOUT        = return Retry@@ -121,8 +121,8 @@     putMVar mvar (Right wr)     return EndOperation   where-    com_pos      = getField $ deleteCompletedCommitPosition wec-    pre_pos      = getField $ deleteCompletedPreparePosition wec+    com_pos      = getField $ _deleteCompletedCommitPosition wec+    pre_pos      = getField $ _deleteCompletedPreparePosition wec     com_pos_int  = fromMaybe (-1) com_pos     pre_pos_int  = fromMaybe (-1) pre_pos     pos          = Position com_pos_int pre_pos_int
Database/EventStore/Internal/Operation/ReadStreamEventsOperation.hs view
@@ -33,11 +33,11 @@ -------------------------------------------------------------------------------- data ReadStreamEvents     = ReadStreamEvents-      { readStreamId             :: Required 1 (Value Text)-      , readStreamEventNumber    :: Required 2 (Value Int32)-      , readStreamMaxCount       :: Required 3 (Value Int32)-      , readStreamResolveLinkTos :: Required 4 (Value Bool)-      , readStreamRequireMaster  :: Required 5 (Value Bool)+      { _readStreamId             :: Required 1 (Value Text)+      , _readStreamEventNumber    :: Required 2 (Value Int32)+      , _readStreamMaxCount       :: Required 3 (Value Int32)+      , _readStreamResolveLinkTos :: Required 4 (Value Bool)+      , _readStreamRequireMaster  :: Required 5 (Value Bool)       }     deriving (Generic, Show) @@ -50,11 +50,11 @@                     -> ReadStreamEvents newReadStreamEvents stream_id evt_num max_c res_link_tos req_master =     ReadStreamEvents-    { readStreamId             = putField stream_id-    , readStreamEventNumber    = putField evt_num-    , readStreamMaxCount       = putField max_c-    , readStreamResolveLinkTos = putField res_link_tos-    , readStreamRequireMaster  = putField req_master+    { _readStreamId             = putField stream_id+    , _readStreamEventNumber    = putField evt_num+    , _readStreamMaxCount       = putField max_c+    , _readStreamResolveLinkTos = putField res_link_tos+    , _readStreamRequireMaster  = putField req_master     }  --------------------------------------------------------------------------------@@ -73,13 +73,13 @@ -------------------------------------------------------------------------------- data ReadStreamEventsCompleted     = ReadStreamEventsCompleted-      { readSECEvents             :: Repeated 1 (Message ResolvedIndexedEvent)-      , readSECResult             :: Required 2 (Enumeration ReadStreamResult)-      , readSECNextNumber         :: Required 3 (Value Int32)-      , readSECLastNumber         :: Required 4 (Value Int32)-      , readSECEndOfStream        :: Required 5 (Value Bool)-      , readSECLastCommitPosition :: Required 6 (Value Int64)-      , readSECError              :: Optional 7 (Value Text)+      { _readSECEvents             :: Repeated 1 (Message ResolvedIndexedEvent)+      , _readSECResult             :: Required 2 (Enumeration ReadStreamResult)+      , _readSECNextNumber         :: Required 3 (Value Int32)+      , _readSECLastNumber         :: Required 4 (Value Int32)+      , _readSECEndOfStream        :: Required 5 (Value Bool)+      , _readSECLastCommitPosition :: Required 6 (Value Int64)+      , _readSECError              :: Optional 7 (Value Text)       }     deriving (Generic, Show) @@ -108,15 +108,15 @@                      -> StreamEventsSlice newStreamEventsSlice stream_id start dir reco = ses   where-    evts = getField $ readSECEvents reco+    evts = getField $ _readSECEvents reco      ses = StreamEventsSlice-          { streamEventsSliceResult    = getField $ readSECResult reco+          { streamEventsSliceResult    = getField $ _readSECResult reco           , streamEventsSliceStreamId  = stream_id           , streamEventsSliceStart     = start-          , streamEventsSliceNext      = getField $ readSECNextNumber reco-          , streamEventsSliceLast      = getField $ readSECLastNumber reco-          , streamEventsSliceIsEOS     = getField $ readSECEndOfStream reco+          , streamEventsSliceNext      = getField $ _readSECNextNumber reco+          , streamEventsSliceLast      = getField $ _readSECLastNumber reco+          , streamEventsSliceIsEOS     = getField $ _readSECEndOfStream reco           , streamEventsSliceEvents    = fmap newResolvedEvent evts           , streamEventsSliceDirection = dir           }@@ -164,9 +164,9 @@         -> Int32         -> ReadStreamEventsCompleted         -> IO Decision-inspect mvar dir stream_id start rsec = go (getField $ readSECResult rsec)+inspect mvar dir stream_id start rsec = go (getField $ _readSECResult rsec)   where-    may_err = getField $ readSECError rsec+    may_err = getField $ _readSECError rsec      go RS_ERROR         = failed mvar (ServerError may_err)     go RS_ACCESS_DENIED = failed mvar (AccessDenied stream_id)
Database/EventStore/Internal/Operation/WriteEventsOperation.hs view
@@ -32,10 +32,10 @@ -------------------------------------------------------------------------------- data WriteEvents     = WriteEvents-      { writeStreamId        :: Required 1 (Value Text)-      , writeExpectedVersion :: Required 2 (Value Int32)-      , writeEvents          :: Repeated 3 (Message NewEvent)-      , writeRequireMaster   :: Required 4 (Value Bool)+      { _writeStreamId        :: Required 1 (Value Text)+      , _writeExpectedVersion :: Required 2 (Value Int32)+      , _writeEvents          :: Repeated 3 (Message NewEvent)+      , _writeRequireMaster   :: Required 4 (Value Bool)       }     deriving (Generic, Show) @@ -50,21 +50,21 @@                -> WriteEvents newWriteEvents stream_id exp_ver evts req_master =     WriteEvents-    { writeStreamId        = putField stream_id-    , writeExpectedVersion = putField exp_ver-    , writeEvents          = putField evts-    , writeRequireMaster   = putField req_master+    { _writeStreamId        = putField stream_id+    , _writeExpectedVersion = putField exp_ver+    , _writeEvents          = putField evts+    , _writeRequireMaster   = putField req_master     }  -------------------------------------------------------------------------------- data WriteEventsCompleted     = WriteEventsCompleted-      { writeCompletedResult          :: Required 1 (Enumeration OpResult)-      , writeCompletedMessage         :: Optional 2 (Value Text)-      , writeCompletedFirstNumber     :: Required 3 (Value Int32)-      , writeCompletedLastNumber      :: Required 4 (Value Int32)-      , writeCompletedPreparePosition :: Optional 5 (Value Int64)-      , writeCompletedCommitPosition  :: Optional 6 (Value Int64)+      { _writeCompletedResult          :: Required 1 (Enumeration OpResult)+      , _writeCompletedMessage         :: Optional 2 (Value Text)+      , _writeCompletedFirstNumber     :: Required 3 (Value Int32)+      , _writeCompletedLastNumber      :: Required 4 (Value Int32)+      , _writeCompletedPreparePosition :: Optional 5 (Value Int64)+      , _writeCompletedCommitPosition  :: Optional 6 (Value Int64)       }     deriving (Generic, Show) @@ -105,7 +105,7 @@         -> ExpectedVersion         -> WriteEventsCompleted         -> IO Decision-inspect mvar stream exp_ver wec = go (getField $ writeCompletedResult wec)+inspect mvar stream exp_ver wec = go (getField $ _writeCompletedResult wec)   where     go OP_SUCCESS                = succeed mvar wec     go OP_PREPARE_TIMEOUT        = return Retry@@ -126,9 +126,9 @@     putMVar mvar (Right wr)     return EndOperation   where-    last_evt_num = getField $ writeCompletedLastNumber wec-    com_pos      = getField $ writeCompletedCommitPosition wec-    pre_pos      = getField $ writeCompletedPreparePosition wec+    last_evt_num = getField $ _writeCompletedLastNumber wec+    com_pos      = getField $ _writeCompletedCommitPosition wec+    pre_pos      = getField $ _writeCompletedPreparePosition wec     com_pos_int  = fromMaybe (-1) com_pos     pre_pos_int  = fromMaybe (-1) pre_pos     pos          = Position com_pos_int pre_pos_int
Database/EventStore/Internal/Processor.hs view
@@ -32,7 +32,6 @@  -------------------------------------------------------------------------------- import Control.Concurrent.Async-import Data.Text (Text) import Data.UUID import FRP.Sodium import Network
Database/EventStore/Internal/Reader.hs view
@@ -47,10 +47,6 @@ getLengthPrefix = fmap fromIntegral getWord32le  ---------------------------------------------------------------------------------authOffset :: Int-authOffset = 18---------------------------------------------------------------------------------- getPackage :: Get Package getPackage = do     cmd  <- getWord8
README.md view
@@ -11,11 +11,12 @@   6. ReadAllEvents (Forward and Backward)   7. Volatile subscriptions   8. Authentication+  9. Catchup subscriptions  TODO ==== -  1. All kind of Subscriptions+  1. Persistent Subscriptions   2. SSL  Requirements
eventstore.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.3.0.0+version:             0.3.1.0  -- A short (one-line) description of the package. synopsis: EventStore Haskell TCP Client@@ -34,6 +34,7 @@ -- A copyright notice. -- copyright: +homepage:            http://github.com/YoEight/eventstore category:            Database  build-type:          Simple@@ -54,7 +55,8 @@   exposed-modules: Database.EventStore    -- Modules included in this library but not exported.-  other-modules:   Database.EventStore.Internal.Packages+  other-modules:   Database.EventStore.Catchup+                   Database.EventStore.Internal.Packages                    Database.EventStore.Internal.Processor                    Database.EventStore.Internal.Reader                    Database.EventStore.Internal.Types@@ -91,4 +93,6 @@   -- hs-source-dirs:    -- Base language which the package is written in.+  ghc-options: -Wall+   default-language:    Haskell2010