packages feed

eventstore 0.9.1.3 → 0.10.0.0

raw patch · 7 files changed

+140/−90 lines, 7 filesdep −attoparsecPVP ok

version bump matches the API change (PVP)

Dependencies removed: attoparsec

API changes (from Hackage documentation)

+ Database.EventStore: timeSpanTotalDays :: TimeSpan -> Double
+ Database.EventStore: timeSpanTotalHours :: TimeSpan -> Double
+ Database.EventStore: timeSpanTotalMinutes :: TimeSpan -> Double
+ Database.EventStore: timeSpanTotalSeconds :: TimeSpan -> Double
+ Database.EventStore: withBinary :: ByteString -> EventData
+ Database.EventStore: withBinaryAndMetadata :: ByteString -> ByteString -> EventData
- Database.EventStore: timeSpanTotalMillis :: TimeSpan -> Int64
+ Database.EventStore: timeSpanTotalMillis :: TimeSpan -> Double

Files

CHANGELOG.markdown view
@@ -1,3 +1,12 @@+0.10.0.0+--------+* Fix $maxAge and $cacheControl TimeSpan metadata serialization.+* Fix `timeSpanFrom*` functions.+* Implement `timeSpanTotalDays`, `timeSpanTotalHours`, `timeSpanTotalMinutes` and `timeSpanTotalSeconds`.+* Add `withBinary` and `withBinaryAndMetadata`.+* Remove useless `TimeSpan` `ToJSON` and `FromJSON` instances.+* Drop `attoparsec` dependency.+ 0.9.1.3 ------- * Increase cereal upper bound to <0.6
Database/EventStore.hs view
@@ -34,6 +34,8 @@     , createEvent     , withJson     , withJsonAndMetadata+    , withBinary+    , withBinaryAndMetadata      -- * Read Operations     , StreamMetadataResult(..)     , readEvent@@ -96,6 +98,10 @@     , timeSpanFromMinutes     , timeSpanFromHours     , timeSpanFromDays+    , timeSpanTotalDays+    , timeSpanTotalHours+    , timeSpanTotalMinutes+    , timeSpanTotalSeconds     , timeSpanTotalMillis       -- * Transaction     , Transaction
Database/EventStore/Internal/Manager/Subscription/Message.hs view
@@ -132,14 +132,22 @@     , cpsStreamId          = putField stream     , cpsResolveLinkTos    = putField $ psSettingsResolveLinkTos sett     , cpsStartFrom         = putField $ psSettingsStartFrom sett-    , cpsMsgTimeout        = putField $ ms $ psSettingsMsgTimeout sett+    , cpsMsgTimeout        = putField+                             . fromIntegral+                             . (truncate :: Double -> Int64)+                             . timeSpanTotalMillis+                             $ psSettingsMsgTimeout sett     , cpsRecordStats       = putField $ psSettingsExtraStats sett     , cpsLiveBufSize       = putField $ psSettingsLiveBufSize sett     , cpsReadBatchSize     = putField $ psSettingsReadBatchSize sett     , cpsBufSize           = putField $ psSettingsHistoryBufSize sett     , cpsMaxRetryCount     = putField $ psSettingsMaxRetryCount sett     , cpsPreferRoundRobin  = putField False-    , cpsChkPtAfterTime    = putField $ ms $ psSettingsCheckPointAfter sett+    , cpsChkPtAfterTime    = putField+                             . fromIntegral+                             . (truncate :: Double -> Int64)+                             . timeSpanTotalMillis+                             $ psSettingsCheckPointAfter sett     , cpsChkPtMaxCount     = putField $ psSettingsMaxCheckPointCount sett     , cpsChkPtMinCount     = putField $ psSettingsMinCheckPointCount sett     , cpsSubMaxCount       = putField $ psSettingsMaxSubsCount sett@@ -147,7 +155,6 @@     }   where     strText = strategyText $ psSettingsNamedConsumerStrategy sett-    ms      = fromIntegral . timeSpanTotalMillis  -------------------------------------------------------------------------------- instance Encode CreatePersistentSubscription@@ -246,14 +253,22 @@     , upsStreamId          = putField stream     , upsResolveLinkTos    = putField $ psSettingsResolveLinkTos sett     , upsStartFrom         = putField $ psSettingsStartFrom sett-    , upsMsgTimeout        = putField $ ms $ psSettingsMsgTimeout sett+    , upsMsgTimeout        = putField+                             . fromIntegral+                             . (truncate :: Double -> Int64)+                             . timeSpanTotalMillis+                             $ psSettingsMsgTimeout sett     , upsRecordStats       = putField $ psSettingsExtraStats sett     , upsLiveBufSize       = putField $ psSettingsLiveBufSize sett     , upsReadBatchSize     = putField $ psSettingsReadBatchSize sett     , upsBufSize           = putField $ psSettingsHistoryBufSize sett     , upsMaxRetryCount     = putField $ psSettingsMaxRetryCount sett     , upsPreferRoundRobin  = putField False-    , upsChkPtAfterTime    = putField $ ms $ psSettingsCheckPointAfter sett+    , upsChkPtAfterTime    = putField+                             . fromIntegral+                             . (truncate :: Double -> Int64)+                             . timeSpanTotalMillis+                             $ psSettingsCheckPointAfter sett     , upsChkPtMaxCount     = putField $ psSettingsMaxCheckPointCount sett     , upsChkPtMinCount     = putField $ psSettingsMinCheckPointCount sett     , upsSubMaxCount       = putField $ psSettingsMaxSubsCount sett@@ -261,7 +276,6 @@     }   where     strText = strategyText $ psSettingsNamedConsumerStrategy sett-    ms      = fromIntegral . timeSpanTotalMillis  -------------------------------------------------------------------------------- instance Encode UpdatePersistentSubscription
Database/EventStore/Internal/TimeSpan.hs view
@@ -27,18 +27,19 @@     , timeSpanFromMinutes     , timeSpanFromHours     , timeSpanFromDays+    , timeSpanTotalDays+    , timeSpanTotalHours+    , timeSpanTotalMinutes+    , timeSpanTotalSeconds     , timeSpanTotalMillis     ) where  ---------------------------------------------------------------------------------import Control.Applicative import Data.Int import Data.Monoid import Prelude  ---------------------------------------------------------------------------------import Data.Aeson-import Data.Attoparsec.Text import Data.Text.Lazy (unpack) import Data.Text.Lazy.Builder @@ -51,66 +52,6 @@     show = unpack . toLazyText . timeSpanBuilder  ---------------------------------------------------------------------------------instance ToJSON TimeSpan where-    toJSON = toJSON . toLazyText . timeSpanBuilder-----------------------------------------------------------------------------------instance FromJSON TimeSpan where-    parseJSON (String s) =-        case parseOnly parseTimeSpan s of-            Left e   -> fail e-            Right ts -> return ts-    parseJSON _ = empty------------------------------------------------------------------------------------- | Determines weither a number is positive or negative.-parseFormatLiteral :: Parser FormatLiteral-parseFormatLiteral = do-    c <- peekChar'-    case c of-        '-' -> fmap (const Negative) anyChar-        _   -> return Positive-----------------------------------------------------------------------------------parseDays :: Parser Int64-parseDays = option 0 (decimal <* char '.')-----------------------------------------------------------------------------------parseHours :: Parser Int64-parseHours = decimal <* char ':'-----------------------------------------------------------------------------------parseMinutes :: Parser Int64-parseMinutes = parseHours-----------------------------------------------------------------------------------parseSeconds :: Parser Int64-parseSeconds = decimal-----------------------------------------------------------------------------------parseMillis :: Parser Int64-parseMillis = option 0 (char '.' >> decimal)-----------------------------------------------------------------------------------parseBaseTimeSpan :: Parser TimeSpan-parseBaseTimeSpan =-    timeSpanDaysHoursMinsSecsMillis <$>-    parseDays                       <*>-    parseHours                      <*>-    parseMinutes                    <*>-    parseSeconds                    <*>-    parseMillis-----------------------------------------------------------------------------------parseTimeSpan :: Parser TimeSpan-parseTimeSpan = do-    lit             <- parseFormatLiteral-    ts@(TimeSpan i) <- parseBaseTimeSpan-    case lit of-        Negative -> return $ TimeSpan $ negate i-        Positive -> return ts---------------------------------------------------------------------------------- millisPerSecond :: Int64 millisPerSecond = 1000 @@ -147,6 +88,22 @@ ticksPerDay = ticksPerHour * 24  --------------------------------------------------------------------------------+daysPerTick :: Double+daysPerTick = 1 / (realToFrac ticksPerDay)++--------------------------------------------------------------------------------+hoursPerTick :: Double+hoursPerTick = 1 / (realToFrac ticksPerHour)++--------------------------------------------------------------------------------+minutesPerTick :: Double+minutesPerTick = 1 / (realToFrac ticksPerMinute)++--------------------------------------------------------------------------------+secondsPerTick :: Double+secondsPerTick = 1 / (realToFrac ticksPerSecond)++-------------------------------------------------------------------------------- millisPerTick :: Double millisPerTick = 1 / (realToFrac ticksPerMillisecond) @@ -274,13 +231,37 @@  -------------------------------------------------------------------------------- -- | Gets the value of the current 'TimeSpan' structure expressed in whole and+--   fractional days.+timeSpanTotalDays :: TimeSpan -> Double+timeSpanTotalDays (TimeSpan i) = (realToFrac i) * daysPerTick++--------------------------------------------------------------------------------+-- | Gets the value of the current 'TimeSpan' structure expressed in whole and+--   fractional hours.+timeSpanTotalHours :: TimeSpan -> Double+timeSpanTotalHours (TimeSpan i) = (realToFrac i) * hoursPerTick++--------------------------------------------------------------------------------+-- | Gets the value of the current 'TimeSpan' structure expressed in whole and+--   fractional minutes.+timeSpanTotalMinutes :: TimeSpan -> Double+timeSpanTotalMinutes (TimeSpan i) = (realToFrac i) * minutesPerTick++--------------------------------------------------------------------------------+-- | Gets the value of the current 'TimeSpan' structure expressed in whole and+--   fractional seconds.+timeSpanTotalSeconds :: TimeSpan -> Double+timeSpanTotalSeconds (TimeSpan i) = (realToFrac i) * secondsPerTick++--------------------------------------------------------------------------------+-- | Gets the value of the current 'TimeSpan' structure expressed in whole and --   fractional milliseconds.-timeSpanTotalMillis :: TimeSpan -> Int64+timeSpanTotalMillis :: TimeSpan -> Double timeSpanTotalMillis (TimeSpan i) =     let tmp = (realToFrac i) * millisPerTick in-    if tmp > (realToFrac maxMillis) then maxMillis-    else if tmp < (realToFrac minMillis) then minMillis-         else truncate tmp+    if tmp > (realToFrac maxMillis) then realToFrac maxMillis+    else if tmp < (realToFrac minMillis) then realToFrac minMillis+         else tmp  -------------------------------------------------------------------------------- data FormatLiteral = Positive | Negative@@ -353,6 +334,6 @@ interval :: Double -> Int64 -> TimeSpan interval value scale =     let tmp    = value * (realToFrac scale)-        millis = tmp * (if value >= 0 then 0.5 else (-0.5))+        millis = tmp + (if value >= 0 then 0.5 else (-0.5))         res    = truncate (millis * (realToFrac ticksPerMillisecond)) in     TimeSpan res
Database/EventStore/Internal/Types.hs view
@@ -1,8 +1,9 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric      #-}-{-# LANGUAGE DataKinds          #-}-{-# LANGUAGE OverloadedStrings  #-}-{-# LANGUAGE RecordWildCards    #-}+{-# LANGUAGE DeriveDataTypeable  #-}+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE DataKinds           #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE RecordWildCards     #-}+{-# LANGUAGE ScopedTypeVariables #-} -------------------------------------------------------------------------------- -- | -- Module : Database.EventStore.Internal.Types@@ -87,38 +88,53 @@ -- | Holds event data. data EventData     = Json A.Value (Maybe A.Value)+    | Binary ByteString (Maybe ByteString)     deriving (Eq, Show)  -------------------------------------------------------------------------------- -- | Maps 'Event' inner data type to an 'Int32' understandable by the server. eventDataType :: EventData -> Int32 eventDataType (Json _ _) = 1+eventDataType _          = 0  ----------------------------------------------------------------------------------- | Maps 'Event' inner metadata type to an 'Int32' understandable by the server.+-- | Maps 'Event' inner metadata type to an 'Int32' understandable by the+--   server. eventMetadataType :: EventData -> Int32 eventMetadataType _ = 0  ----------------------------------------------------------------------------------- | Creates a event using JSON format+-- | Creates an event using JSON format withJson :: ToJSON a => a -> EventData withJson value = Json (toJSON value) Nothing  ----------------------------------------------------------------------------------- | Create a event with metadata using JSON format+-- | Creates an event using a binary format.+withBinary :: ByteString -> EventData+withBinary bs = Binary bs Nothing++--------------------------------------------------------------------------------+-- | Creates an event with metadata using JSON format. withJsonAndMetadata :: (ToJSON a, ToJSON b) => a -> b -> EventData withJsonAndMetadata value metadata =     Json (toJSON value) (Just $ toJSON metadata)  --------------------------------------------------------------------------------+-- | Creates an event with metadata using binary format.+withBinaryAndMetadata :: ByteString -> ByteString -> EventData+withBinaryAndMetadata value metadata = Binary value (Just metadata)++-------------------------------------------------------------------------------- -- | Serializes 'EventData''s data to a raw 'ByteString'. eventDataBytes :: EventData -> ByteString-eventDataBytes (Json value _) = toStrict $ A.encode value+eventDataBytes (Json value _)   = toStrict $ A.encode value+eventDataBytes (Binary value _) = value  -------------------------------------------------------------------------------- -- | Serializes 'EventData' metadata to a raw 'ByteString'. eventMetadataBytes :: EventData -> Maybe ByteString-eventMetadataBytes (Json _ meta_m) = fmap (toStrict . A.encode) meta_m+eventMetadataBytes (Json _ meta_m)   = fmap (toStrict . A.encode) meta_m+eventMetadataBytes (Binary _ meta_m) = meta_m  -------------------------------------------------------------------------------- -- Expected Version@@ -648,15 +664,18 @@ -- | Serialized a 'StreamMetadata' to 'Value' for serialization purpose. streamMetadataJSON :: StreamMetadata -> A.Value streamMetadataJSON StreamMetadata{..} =-    A.object $ [ p_maxAge         .= streamMetadataMaxAge+    A.object $ [ p_maxAge         .= fmap toInt64 streamMetadataMaxAge                , p_maxCount       .= streamMetadataMaxCount                , p_truncateBefore .= streamMetadataTruncateBefore-               , p_cacheControl   .= streamMetadataCacheControl+               , p_cacheControl   .= fmap toInt64 streamMetadataCacheControl                , p_acl            .= streamACLJSON streamMetadataACL                ] ++ custPairs   where     custPairs = customMetaToPairs streamMetadataCustom +    toInt64 :: TimeSpan -> Int64+    toInt64 = truncate . timeSpanTotalSeconds+ -------------------------------------------------------------------------------- -- Stream ACL Properties --------------------------------------------------------------------------------@@ -755,11 +774,16 @@ parseStreamMetadata (A.Object m) =     StreamMetadata                    <$>     m A..: p_maxCount                 <*>-    m A..: p_maxAge                   <*>+    parseTimeSpan p_maxAge            <*>     m A..: p_truncateBefore           <*>-    m A..: p_cacheControl             <*>+    parseTimeSpan p_cacheControl      <*>     (m A..: p_acl >>= parseStreamACL) <*>     pure (keepUserProperties m)+  where+    parseTimeSpan ::  Text -> Parser (Maybe TimeSpan)+    parseTimeSpan prop = do+        (secs :: Maybe Int64) <- m A..: prop+        return $ fmap (timeSpanFromSeconds . realToFrac) secs parseStreamMetadata _ = mzero  --------------------------------------------------------------------------------
eventstore.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.9.1.3+version:             0.10.0.0  tested-with: GHC >= 7.8.3 && < 7.11 @@ -113,7 +113,6 @@                      , uuid       ==1.3.*                      , unordered-containers                      , stm-                     , attoparsec    -- Directories containing source files.   -- hs-source-dirs:
tests/Tests.hs view
@@ -46,6 +46,7 @@     , testCase "Update persistent sub" $ updatePersistentTest conn     , testCase "Delete persistent sub" $ deletePersistentTest conn     , testCase "Connect persistent sub" $ connectToPersistentTest conn+    , testCase "MaxAge metadata test" $ maxAgeTest conn     , testCase "Shutdown connection" $ shutdownTest conn     ] @@ -303,6 +304,22 @@             return False     res <- catch action $ \(_ :: SubscriptionClosed) -> return True     assertBool "Should have raised an exception" res++--------------------------------------------------------------------------------+maxAgeTest :: Connection -> IO ()+maxAgeTest conn = do+    let timespan = timeSpanFromDays 1+        metadata = buildStreamMetadata $ setMaxAge timespan+        evt = createEvent "foo" Nothing+              $ withJson (object ["type" .= (3 :: Int)])+    _ <- sendEvent conn "test-max-age" anyVersion evt >>= wait+    _ <- setStreamMetadata conn "test-max-age" anyVersion metadata >>= wait+    r <- getStreamMetadata conn "test-max-age" >>= wait+    case r of+        StreamMetadataResult _ _ m ->+            assertEqual "Should have equal timespan" (Just timespan)+            (streamMetadataMaxAge m)+        _ -> fail "Stream test-max-age doesn't exist"  -------------------------------------------------------------------------------- shutdownTest :: Connection -> IO ()