packages feed

eventstore 0.7.0.1 → 0.7.1.0

raw patch · 10 files changed

+151/−90 lines, 10 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Database.EventStore: MaxAttempt :: HostName -> Int -> Int -> ConnectionException
+ Database.EventStore: data ConnectionException
- Database.EventStore: createEvent :: Text -> EventData -> Event
+ Database.EventStore: createEvent :: Text -> Maybe UUID -> EventData -> Event

Files

CHANGELOG.markdown view
@@ -1,3 +1,8 @@+0.7.1.0+-------+* Internal connection changes+* Allow creating an event with an existing ID+ 0.7.0.1 ------- * Tight package channnel to connection instance in order to prevent loss on connection drops.
Database/EventStore.hs view
@@ -20,6 +20,7 @@     , withJsonAndMetadata       -- * Connection     , Connection+    , ConnectionException(..)     , Credentials     , Settings(..)     , Retry
+ Database/EventStore/Internal/Connection.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE ScopedTypeVariables #-}+--------------------------------------------------------------------------------+-- |+-- Module : Database.EventStore.Internal.Connection+-- Copyright : (C) 2015 Yorick Laupa+-- License : (see the file LICENSE)+--+-- Maintainer : Yorick Laupa <yo.eight@gmail.com>+-- Stability : provisional+-- Portability : non-portable+--+--------------------------------------------------------------------------------+module Database.EventStore.Internal.Connection+    ( Connection+    , ConnectionException(..)+    , connUUID+    , connClose+    , connFlush+    , connSend+    , connRecv+    , newConnection+    ) where++--------------------------------------------------------------------------------+import           Control.Concurrent+import           Control.Exception+import qualified Data.ByteString as B+import           Data.Typeable+import           System.IO+import           Text.Printf++--------------------------------------------------------------------------------+import Data.UUID+import Network+import System.Random++--------------------------------------------------------------------------------+import Database.EventStore.Internal.Types++--------------------------------------------------------------------------------+data ConnectionException =+    MaxAttempt HostName Int Int -- ^ HostName Port MaxAttempt's value+    deriving (Show, Typeable)++--------------------------------------------------------------------------------+instance Exception ConnectionException++--------------------------------------------------------------------------------+data Connection =+    Connection+    { connUUID  :: UUID+    , connClose :: IO ()+    , connFlush :: IO ()+    , connSend  :: B.ByteString -> IO ()+    , connRecv  :: Int -> IO B.ByteString+    }++--------------------------------------------------------------------------------+newConnection :: Settings -> HostName -> Int -> IO Connection+newConnection sett host port =+    case s_retry sett of+        AtMost n ->+            let loop i = do+                    printf "Connecting...Attempt %d\n" i+                    catch (connect sett host port) $ \(_ :: SomeException) -> do+                        threadDelay delay+                        if n <= i then throwIO $ MaxAttempt host port n+                                  else loop (i + 1) in+             loop 1+        KeepRetrying ->+            let endlessly i = do+                    printf "Connecting...Attempt %d\n" i+                    catch (connect sett host port) $ \(_ :: SomeException) -> do+                        threadDelay delay >> endlessly (i + 1) in+             endlessly (1 :: Int)+  where+    delay = (s_reconnect_delay_secs sett) * secs++--------------------------------------------------------------------------------+secs :: Int+secs = 1000000++--------------------------------------------------------------------------------+connect :: Settings -> HostName -> Int -> IO Connection+connect _ host port = do+    hdl <- connectTo host (PortNumber $ fromIntegral port)+    hSetBuffering hdl NoBuffering+    uuid <- randomIO+    return $ regularConnection hdl uuid++--------------------------------------------------------------------------------+regularConnection :: Handle -> UUID -> Connection+regularConnection h uuid =+    Connection+    { connUUID  = uuid+    , connClose = hClose h+    , connFlush = hFlush h+    , connSend  = B.hPut h+    , connRecv  = B.hGet h+    }
Database/EventStore/Internal/Operation/TransactionStartOperation.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP             #-} {-# LANGUAGE RecordWildCards #-} -------------------------------------------------------------------------------- -- |@@ -19,10 +18,8 @@ import Control.Exception import Data.Int import Data.Maybe-#if MIN_VERSION_base(4,8,0)-#else import Data.Traversable-#endif+import Prelude  -------------------------------------------------------------------------------- import Control.Concurrent.Async@@ -262,12 +259,14 @@ eventToNewEvent :: Event -> IO NewEvent eventToNewEvent evt =     newEvent evt_type+             evt_id              evt_data_type              evt_metadata_type              evt_data_bytes              evt_metadata_bytes   where     evt_type           = eventType evt+    evt_id             = eventId evt     evt_data_bytes     = eventDataBytes $ eventData evt     evt_data_type      = eventDataType $ eventData evt     evt_metadata_bytes = eventMetadataBytes $ eventData evt
Database/EventStore/Internal/Operation/WriteEventsOperation.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP           #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DataKinds     #-} --------------------------------------------------------------------------------@@ -19,11 +18,9 @@ import Control.Concurrent import Data.Int import Data.Maybe-#if MIN_VERSION_base(4,8,0)-#else import Data.Traversable-#endif import GHC.Generics (Generic)+import Prelude  -------------------------------------------------------------------------------- import Data.ProtocolBuffers@@ -150,12 +147,14 @@ eventToNewEvent :: Event -> IO NewEvent eventToNewEvent evt =     newEvent evt_type+             evt_id              evt_data_type              evt_metadata_type              evt_data_bytes              evt_metadata_bytes   where     evt_type           = eventType evt+    evt_id             = eventId evt     evt_data_bytes     = eventDataBytes $ eventData evt     evt_data_type      = eventDataType $ eventData evt     evt_metadata_bytes = eventMetadataBytes $ eventData evt
Database/EventStore/Internal/Processor.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE DeriveDataTypeable  #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-} --------------------------------------------------------------------------------@@ -13,7 +12,8 @@ -- -------------------------------------------------------------------------------- module Database.EventStore.Internal.Processor-    ( InternalException(..)+    ( ConnectionException(..)+    , InternalException(..)     , Processor(..)     , DropReason(..)     , NewSubscriptionCB@@ -33,19 +33,16 @@ import Control.Exception import Data.Functor (void) import Data.Monoid ((<>))-import Data.Typeable import Data.Word-import System.IO import Text.Printf  ---------------------------------------------------------------------------------import Control.Concurrent.Async import Data.UUID import FRP.Sodium import Network-import System.Random  --------------------------------------------------------------------------------+import Database.EventStore.Internal.Connection import Database.EventStore.Internal.Manager.Operation import Database.EventStore.Internal.Manager.Subscription import Database.EventStore.Internal.Packages@@ -70,16 +67,6 @@ newProcessor sett = sync . network sett =<< newChan  ----------------------------------------------------------------------------------- Exception----------------------------------------------------------------------------------data ProcessorException-    = MaxAttempt HostName Int Int -- ^ Hostname Port MaxAttempt value-    deriving (Show, Typeable)-----------------------------------------------------------------------------------instance Exception ProcessorException---------------------------------------------------------------------------------- -- State -------------------------------------------------------------------------------- data State@@ -101,7 +88,6 @@ data Reconnect   = Reconnect data Reconnected = Reconnected UUID (IO ()) - -------------------------------------------------------------------------------- heartbeatRequestCmd :: Word8 heartbeatRequestCmd = 0x01@@ -154,7 +140,6 @@                         push_recv_io                         (push_con_io host port)                         push_reco_io-                        onSend                         host                         port @@ -164,7 +149,6 @@                         push_recv_io                         push_recod_io                         push_reco_io-                        onSend                         host                         port @@ -184,6 +168,8 @@             , processorNewSubcription = push_sub             } +    _ <- listen onSend (writeChan chan)+     return processor  --------------------------------------------------------------------------------@@ -204,55 +190,23 @@     }  ---------------------------------------------------------------------------------secs :: Int-secs = 1000000---------------------------------------------------------------------------------- connection :: Settings            -> Chan Package            -> (Package -> IO ())            -> (UUID -> IO () -> IO ())            -> IO ()-           -> Event Package            -> HostName            -> Int            -> IO ()-connection sett chan push_pkg push_con push_reco evt_pkg host port = go-  where-    go =-        case s_retry sett of-            AtMost n ->-                let loop i =-                        catch (doConnect i) $ \(_ :: SomeException) -> do-                            threadDelay delay-                            if n <= i then throwIO $ MaxAttempt host port n-                                      else loop (i + 1) in-                 loop 1-            KeepRetrying ->-                let endlessly i =-                        catch (doConnect i) $ \(_ :: SomeException) ->-                            threadDelay delay >> endlessly (i + 1) in-                endlessly (1 :: Int)--    delay = (s_reconnect_delay_secs sett) * secs--    doConnect att = do-        printf "Connecting...Attempt %d\n" att-        hdl <- connectTo host (PortNumber $ fromIntegral port)-        hSetBuffering hdl NoBuffering--        uuid  <- randomIO-        as_rl <- async $ sync $ listen evt_pkg (writeChan chan)-        rid   <- forkFinally (readerThread push_pkg hdl) (recovering push_reco)-        wid   <- forkFinally (writerThread chan hdl) (recovering push_reco)--        push_con uuid $ do-            throwTo rid Stopped-            throwTo wid Stopped-            hClose hdl-            rel_w <- wait as_rl-            rel_w-            printf "Disconnected %s\n" (toString uuid)+connection sett chan push_pkg push_con push_reco host port = do+    conn <- newConnection sett host port+    rid  <- forkFinally (readerThread push_pkg conn) (recovering push_reco)+    wid  <- forkFinally (writerThread chan conn) (recovering push_reco)+    push_con (connUUID conn) $ do+        throwTo rid Stopped+        throwTo wid Stopped+        connClose conn+        printf "Disconnected %s\n" (toString $ connUUID conn)  -------------------------------------------------------------------------------- recovering :: IO () -> Either SomeException () -> IO ()
Database/EventStore/Internal/Reader.hs view
@@ -12,28 +12,27 @@ module Database.EventStore.Internal.Reader (readerThread) where  ---------------------------------------------------------------------------------import           Prelude hiding (take)-import           Control.Monad-import qualified Data.ByteString as B-import           System.IO-import           Text.Printf+import Prelude hiding (take)+import Control.Monad+import Text.Printf  -------------------------------------------------------------------------------- import Data.Serialize.Get import Data.UUID  --------------------------------------------------------------------------------+import Database.EventStore.Internal.Connection import Database.EventStore.Internal.Types  ---------------------------------------------------------------------------------readerThread :: (Package -> IO ()) -> Handle -> IO ()-readerThread push_p h = forever $ do-    header_bs <- B.hGet h 4+readerThread :: (Package -> IO ()) -> Connection -> IO ()+readerThread push_p c = forever $ do+    header_bs <- connRecv c 4     case runGet getLengthPrefix header_bs of         Left _             -> error "Wrong package framing"         Right length_prefix-            -> B.hGet h length_prefix >>= parsePackage+            -> connRecv c length_prefix >>= parsePackage   where     parsePackage bs =         case runGet getPackage bs of
Database/EventStore/Internal/Types.hs view
@@ -72,12 +72,14 @@ data Event     = Event       { eventType :: !Text+      , eventId   :: !(Maybe UUID)       , eventData :: !EventData       }  ---------------------------------------------------------------------------------createEvent :: Text      -- ^ Event type-            -> EventData -- ^ Event data+createEvent :: Text       -- ^ Event type+            -> Maybe UUID -- ^ Event ID, generated if 'Nothing'+            -> EventData  -- ^ Event data             -> Event createEvent = Event @@ -193,13 +195,14 @@  -------------------------------------------------------------------------------- newEvent :: Text             -- ^ Event type+         -> Maybe UUID       -- ^ Event ID          -> Int32            -- ^ Data content type          -> Int32            -- ^ Metadata content type          -> ByteString       -- ^ Event data          -> Maybe ByteString -- ^ Metadata          -> IO NewEvent-newEvent evt_type data_type meta_type evt_data evt_meta = do-    new_uuid <- randomIO+newEvent evt_type evt_id data_type meta_type evt_data evt_meta = do+    new_uuid <- maybe randomIO return evt_id     let uuid_bytes = toStrict $ toByteString new_uuid         new_evt    = NewEvent                      { newEventId           = putField uuid_bytes
Database/EventStore/Internal/Writer.hs view
@@ -12,21 +12,20 @@ module Database.EventStore.Internal.Writer (writerThread) where  ---------------------------------------------------------------------------------import           Control.Concurrent-import           Control.Monad-import qualified Data.ByteString as B-import           System.IO+import Control.Concurrent+import Control.Monad  -------------------------------------------------------------------------------- import Data.Serialize.Put  --------------------------------------------------------------------------------+import Database.EventStore.Internal.Connection import Database.EventStore.Internal.Packages import Database.EventStore.Internal.Types  ---------------------------------------------------------------------------------writerThread :: Chan Package -> Handle -> IO ()-writerThread chan hdl = forever $ do+writerThread :: Chan Package -> Connection -> IO ()+writerThread chan c = forever $ do     pkg <- readChan chan-    B.hPut hdl (runPut $ putPackage pkg)-    hFlush hdl+    connSend c (runPut $ putPackage pkg)+    connFlush c
eventstore.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.7.0.1+version:             0.7.1.0  -- A short (one-line) description of the package. synopsis: EventStore TCP Client@@ -58,6 +58,7 @@    -- Modules included in this library but not exported.   other-modules:   Database.EventStore.Catchup+                   Database.EventStore.Internal.Connection                    Database.EventStore.Internal.Packages                    Database.EventStore.Internal.Processor                    Database.EventStore.Internal.Reader