packages feed

ez-couch 0.5.1 → 0.6.0

raw patch · 7 files changed

+54/−42 lines, 7 filesdep ~classy-preludedep ~classy-prelude-conduitPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: classy-prelude, classy-prelude-conduit

API changes (from Hackage documentation)

+ EZCouch: type Environment = (ConnectionSettings, Manager, NominalDiffTime)
- EZCouch: class (MonadBaseControl IO m, MonadResource m, MonadReader (ConnectionSettings, Manager) m) => MonadAction m
+ EZCouch: class (MonadBaseControl IO m, MonadResource m, MonadReader Environment m) => MonadAction m
- EZCouch: run :: (MonadIO m, MonadBaseControl IO m, MonadThrow m, MonadUnsafeIO m) => ConnectionSettings -> ReaderT (ConnectionSettings, Manager) (ResourceT m) a -> m a
+ EZCouch: run :: (MonadIO m, MonadBaseControl IO m, MonadThrow m, MonadUnsafeIO m) => ConnectionSettings -> ReaderT (ConnectionSettings, Manager, NominalDiffTime) (ResourceT m) a -> m a
- EZCouch: runWithManager :: (MonadBaseControl IO m, MonadResource m) => Manager -> ConnectionSettings -> ReaderT (ConnectionSettings, Manager) m a -> m a
+ EZCouch: runWithManager :: (MonadBaseControl IO m, MonadResource m) => Manager -> ConnectionSettings -> ReaderT (ConnectionSettings, Manager, NominalDiffTime) m a -> m a

Files

ez-couch.cabal view
@@ -1,5 +1,5 @@ name:               ez-couch-version:            0.5.1+version:            0.6.0 cabal-version:      >=1.8 build-type:         Simple license:            MIT@@ -65,8 +65,8 @@                     random >= 1.0,                     resourcet >= 0.3,                     string-conversions >= 0.2,-                    classy-prelude >= 0.4.4,-                    classy-prelude-conduit >= 0.4,+                    classy-prelude >= 0.5.0,+                    classy-prelude-conduit,                     hashable >= 1.1,                     vector  
src/EZCouch.hs view
@@ -48,6 +48,7 @@    -- * Execution Monad   MonadAction,+  Environment,   run,   runWithManager,   ConnectionSettings(..),@@ -80,11 +81,13 @@ import Control.Monad.Trans.Resource import qualified Network.HTTP.Conduit as HTTP + runWithManager manager settings action = -  flip runReaderT (settings, manager) $ runResourceT $ do-    resourceForkIO $ lift $ Sweeper.runSweeper-    lift $ action+  flip runReaderT (settings, manager, fromIntegral 0) $ do+    timeDeviation <- getTimeDeviation+    withTimeDeviation timeDeviation $ runResourceT $ do+      resourceForkIO $ lift $ Sweeper.runSweeper+      lift $ action  run settings action = HTTP.withManager $ \manager ->    runWithManager manager settings action-
src/EZCouch/Action.hs view
@@ -10,6 +10,7 @@ import EZCouch.Logging import EZCouch.Retry import EZCouch.Crash+import Data.Time import qualified Network.HTTP.Types as HTTP import qualified Network.HTTP.Conduit as HTTP import qualified Network.HTTP.Conduit.Request as HTTP@@ -29,11 +30,12 @@  defaultPort = 5984 :: Int +type Environment = (ConnectionSettings, HTTP.Manager, NominalDiffTime)  -- | All EZCouch operations are performed in this monad.-class (MonadBaseControl IO m, MonadResource m, MonadReader (ConnectionSettings, HTTP.Manager) m) => MonadAction m where+class (MonadBaseControl IO m, MonadResource m, MonadReader Environment m) => MonadAction m where -instance (MonadResource m, MonadBaseControl IO m) => MonadAction (ReaderT (ConnectionSettings, HTTP.Manager) m) +instance (MonadResource m, MonadBaseControl IO m) => MonadAction (ReaderT Environment m)   generateRequest :: (MonadAction m)    => HTTP.Method@@ -42,7 +44,7 @@   -> LByteString   -> m (HTTP.Request m) generateRequest method dbPath qps body = do-  (settings, _) <- ask+  (settings, _, _) <- ask   return $ settingsRequest settings   where     headers = [("Content-Type", "application/json")]@@ -71,12 +73,12 @@   logLn 0 $ "Performing a "      ++ show (HTTP.method request)      ++ " at " ++ show (HTTP.url request)-  (_, manager) <- ask+  (_, manager, _) <- ask   retrying exceptionIntervals $      processResponse =<< http' request manager   where-    exceptionIntervals (ConnectionException {}) = [10^3, 10^6, 10^6*10]-    exceptionIntervals (ServerException {}) = [10^3, 10^6, 10^6*10]+    exceptionIntervals (ConnectionException {}) = map (*10^6) [0, 1, 5]+    exceptionIntervals (ServerException {}) = map (*10^6) [0, 1, 5]     exceptionIntervals _ = []  http' request manager = @@ -138,7 +140,7 @@         Aeson.Success _ ->            throwIO $ ServerException $ "Status " ++ show code ++ " response: " ++ (decodeUtf8 . toStrict . Aeson.encode) json         Aeson.Error m -> -          crash $ (pack) m ++ ". Response body: " ++ (toStrict . decodeUtf8 . Aeson.encode) json+          throwIO $ ServerException $ "Status " ++ show code     _ | code >= 400 ->       crash $ "Unexpected status code: " ++ show code ++ ", " ++ (decodeUtf8) msg     _ -> return $ ResponseOk response
src/EZCouch/Parsing.hs view
@@ -3,8 +3,6 @@  import Prelude () import ClassyPrelude-import Control.Monad.Trans.Resource-import qualified Data.Text.Lazy as Text import EZCouch.Types import Data.Aeson as Aeson  @@ -16,12 +14,12 @@ rowsParser1 :: Parser (Vector Aeson.Value) rowsParser1 json   | Just (Aeson.Array rows) <- json .? "rows" = Right rows-  | otherwise = Left $ unexpectedJSONValue json+  | otherwise = Left $ unexpectedJSONValue "rowsParser1" json  rowsParser2 :: Parser (Vector Aeson.Value) rowsParser2 json   | Aeson.Array rows <- json = Right rows-  | otherwise = Left $ unexpectedJSONValue json+  | otherwise = Left $ unexpectedJSONValue "rowsParser2" json  idRevParser :: Parser (Text, Maybe Text) idRevParser o @ (Aeson.Object m) @@ -33,7 +31,7 @@     Just id <- lookup "id" m     = (,) <$> fromJSON' id <*> pure Nothing   | otherwise-    = Left $ unexpectedJSONValue o+    = Left $ unexpectedJSONValue "idRevParser" o  keyExistsParser :: (FromJSON k) => Parser (k, Bool) keyExistsParser o @ (Aeson.Object m) @@ -49,7 +47,7 @@     Just key <- lookup "key" m     = (,) <$> fromJSON' key <*> pure True   | otherwise-    = Left $ unexpectedJSONValue o+    = Left $ unexpectedJSONValue "keyExistsParser" o  persistedParser :: (FromJSON a) => Parser (Maybe (Persisted a)) persistedParser o@@ -59,8 +57,10 @@     Just doc <- o .? "doc",     Just rev <- doc .? "_rev"     = fmap Just $ Persisted <$> fromJSON' id <*> fromJSON' rev <*> fromJSON' doc+  | o .? "doc" == Just Aeson.Null+    = Right Nothing   | otherwise-    = Left $ unexpectedJSONValue o+    = Left $ unexpectedJSONValue "persistedParser" o  errorPersistedParser :: (FromJSON a) => Parser (Either (Text, Text) (Persisted a)) errorPersistedParser o @ (Aeson.Object m) @@ -70,7 +70,7 @@   | Just error <- lookup "error" m, Just reason <- lookup "reason" m     = fmap Left $ (,) <$> fromJSON' error <*> fromJSON' reason    | otherwise-    = Left $ unexpectedJSONValue o+    = Left $ unexpectedJSONValue "errorPersistedParser" o  maybePersistedByKeyParser :: (FromJSON a, FromJSON k) => Parser (k, Maybe (Persisted a)) maybePersistedByKeyParser o @ (Aeson.Object m) @@ -94,7 +94,7 @@     Just key <- lookup "key" m     = (,) <$> fromJSON' key <*> pure Nothing   | otherwise-    = Left $ unexpectedJSONValue o+    = Left $ unexpectedJSONValue "maybePersistedByKeyParser" o   @@ -103,10 +103,12 @@   Aeson.Error s -> Left $ "fromJSON failed with a message `"      ++ fromString s      ++ "` on the following value: " -    ++ (Text.toStrict . decodeUtf8 $ Aeson.encode json) +    ++ (toStrict . decodeUtf8 $ Aeson.encode json)  -unexpectedJSONValue json = -  "Unexpected JSON value: " ++ (Text.toStrict . decodeUtf8 $ Aeson.encode json)+unexpectedJSONValue parserName json = +  parserName ++ ": "+    ++ "Unexpected JSON value: " +    ++ (toStrict . decodeUtf8 $ Aeson.encode json)  o .? k = pure o ?.? k o ?.? k = o >>= objectKey k
src/EZCouch/Retry.hs view
@@ -7,16 +7,6 @@ import EZCouch.Logging  -retryingEither [] action = action -retryingEither (i:is) action = action >>= processResult-  where -    processResult (Left _) -      | i == 0 = retryingEither is action-      | otherwise = liftIO (threadDelay i) >> retryingEither is action-    processResult r = return r--retryingEither' = retryingEither defaultIntervals- retrying exceptionIntervals action = retrying_ 0   where     retrying_ attempt = catch action processException
src/EZCouch/Time.hs view
@@ -6,14 +6,18 @@ import System.Locale import Data.Time import qualified Network.HTTP.Types as HTTP-+import Control.Monad.Reader import EZCouch.Types import EZCouch.Action --- | Current time according to server.+-- | Current time according to server. This function doesn't actually emit any+-- requests to the server, calculating the value from a deviation of local time+-- from server time determined at the beginning of the EZCouch session. readTime :: MonadAction m => m UTCTime -readTime = getResponseHeaders HTTP.methodGet mempty mempty mempty-  >>= getHeadersTime+readTime = do+  (_, _, deviation) <- ask+  localTime <- liftIO $ getCurrentTime+  return $ addUTCTime deviation localTime  getHeadersTime ((name, value) : tail)    | name == HTTP.hDate = case toTime value of@@ -24,3 +28,14 @@  toTime = parseTime defaultTimeLocale "%a, %d %b %Y %H:%M:%S %Z"    . unpack . asText . decodeUtf8++getTimeDeviation :: MonadAction m => m NominalDiffTime +getTimeDeviation = do+  dbTime <- getResponseHeaders HTTP.methodGet mempty mempty mempty+    >>= getHeadersTime+  localTime <- liftIO $ getCurrentTime+  return $ diffUTCTime dbTime localTime++withTimeDeviation :: (MonadAction m) => NominalDiffTime -> m a -> m a+withTimeDeviation timeDeviation =+  local (\(settings, manager, _) -> (settings, manager, timeDeviation)) 
src/EZCouch/WriteAction.hs view
@@ -61,7 +61,7 @@  createIdentifiedEntities :: (MonadAction m, ToJSON a)    => [Identified a]-  -> m [Either (Text, a) (Persisted a)]+  -> m [Either (Identified a) (Persisted a)] createIdentifiedEntities idsToVals    = writeOperationsAction [Create id val | (id, val) <- idsToVals]       >>= mapM convertResult@@ -118,4 +118,4 @@      lookupThrowing id cache = case lookup id cache of   Just val -> return val-  Nothing -> throwIO $ ParsingException $ "Unexpected id: " ++ show id+  Nothing -> throwIO $ ResponseException $ "Unexpected id: " ++ show id