packages feed

avers 0.0.8 → 0.0.9

raw patch · 5 files changed

+94/−52 lines, 5 filesdep +network-uridep +safedep ~clockdep ~rethinkdb-client-driverPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: network-uri, safe

Dependency ranges changed: clock, rethinkdb-client-driver

API changes (from Hackage documentation)

- Avers: AversConfig :: !Text -> !Text -> (BlobId -> Text -> ByteString -> IO ()) -> ![SomeObjectType] -> (Measurement -> Double -> IO ()) -> AversConfig
- Avers: data AversConfig
- Avers: data AversState
- Avers: databaseHost :: AversConfig -> !Text
- Avers: databaseName :: AversConfig -> !Text
- Avers.Types: AversConfig :: !Text -> !Text -> (BlobId -> Text -> ByteString -> IO ()) -> ![SomeObjectType] -> (Measurement -> Double -> IO ()) -> AversConfig
- Avers.Types: AversState :: !AversConfig -> !(Pool Handle) -> !(TVar (Map ObjectId RevId)) -> AversState
- Avers.Types: data AversConfig
- Avers.Types: data AversState
- Avers.Types: databaseName :: AversConfig -> !Text
- Avers.Types: instance MonadState AversState Avers
+ Avers: Config :: !URI -> (BlobId -> Text -> ByteString -> IO (Either AversError ())) -> ![SomeObjectType] -> (Measurement -> Double -> IO ()) -> Config
+ Avers: data Config
+ Avers: data Handle
+ Avers: databaseURI :: Config -> !URI
+ Avers.Types: Config :: !URI -> (BlobId -> Text -> ByteString -> IO (Either AversError ())) -> ![SomeObjectType] -> (Measurement -> Double -> IO ()) -> Config
+ Avers.Types: Handle :: !Config -> !(Pool Handle) -> !(TVar (Map ObjectId RevId)) -> Handle
+ Avers.Types: data Config
+ Avers.Types: data Handle
+ Avers.Types: databaseAuth :: Config -> Maybe Text
+ Avers.Types: databasePort :: Config -> Int
+ Avers.Types: databaseURI :: Config -> !URI
+ Avers.Types: extractDatabaseName :: Config -> Either AversError Text
+ Avers.Types: instance MonadState Handle Avers
- Avers: emitMeasurement :: AversConfig -> Measurement -> Double -> IO ()
+ Avers: emitMeasurement :: Config -> Measurement -> Double -> IO ()
- Avers: evalAvers :: AversState -> Avers a -> IO (Either AversError a)
+ Avers: evalAvers :: Handle -> Avers a -> IO (Either AversError a)
- Avers: newState :: AversConfig -> IO AversState
+ Avers: newState :: Config -> IO (Either AversError Handle)
- Avers: objectTypes :: AversConfig -> ![SomeObjectType]
+ Avers: objectTypes :: Config -> ![SomeObjectType]
- Avers: putBlob :: AversConfig -> BlobId -> Text -> ByteString -> IO ()
+ Avers: putBlob :: Config -> BlobId -> Text -> ByteString -> IO (Either AversError ())
- Avers.Types: Avers :: StateT AversState (ExceptT AversError IO) a -> Avers a
+ Avers.Types: Avers :: StateT Handle (ExceptT AversError IO) a -> Avers a
- Avers.Types: config :: AversState -> !AversConfig
+ Avers.Types: config :: Handle -> !Config
- Avers.Types: databaseHandlePool :: AversState -> !(Pool Handle)
+ Avers.Types: databaseHandlePool :: Handle -> !(Pool Handle)
- Avers.Types: databaseHost :: AversConfig -> !Text
+ Avers.Types: databaseHost :: Config -> Either AversError Text
- Avers.Types: emitMeasurement :: AversConfig -> Measurement -> Double -> IO ()
+ Avers.Types: emitMeasurement :: Config -> Measurement -> Double -> IO ()
- Avers.Types: evalAvers :: AversState -> Avers a -> IO (Either AversError a)
+ Avers.Types: evalAvers :: Handle -> Avers a -> IO (Either AversError a)
- Avers.Types: newDatabaseHandlePool :: AversConfig -> IO (Pool Handle)
+ Avers.Types: newDatabaseHandlePool :: Config -> Text -> ExceptT AversError IO (Pool Handle)
- Avers.Types: newState :: AversConfig -> IO AversState
+ Avers.Types: newState :: Config -> IO (Either AversError Handle)
- Avers.Types: objectTypes :: AversConfig -> ![SomeObjectType]
+ Avers.Types: objectTypes :: Config -> ![SomeObjectType]
- Avers.Types: putBlob :: AversConfig -> BlobId -> Text -> ByteString -> IO ()
+ Avers.Types: putBlob :: Config -> BlobId -> Text -> ByteString -> IO (Either AversError ())
- Avers.Types: recentRevisionCache :: AversState -> !(TVar (Map ObjectId RevId))
+ Avers.Types: recentRevisionCache :: Handle -> !(TVar (Map ObjectId RevId))
- Avers.Types: runAvers :: Avers a -> StateT AversState (ExceptT AversError IO) a
+ Avers.Types: runAvers :: Avers a -> StateT Handle (ExceptT AversError IO) a

Files

avers.cabal view
@@ -1,5 +1,5 @@ name:                avers-version:             0.0.8+version:             0.0.9 license:             GPL-3 license-file:        LICENSE author:              Tomas Carnecky@@ -51,11 +51,13 @@       , attoparsec       , base <= 9999       , bytestring-      , clock                    >= 0.4.4.0 && < 0.5+      , clock       , containers       , filepath       , mtl       , network+      , network-uri+      , safe       , stm       , template-haskell       , text@@ -70,7 +72,7 @@       , cryptohash       , inflections       , resource-pool-      , rethinkdb-client-driver >= 0.0.17+      , rethinkdb-client-driver >= 0.0.19       , scrypt  @@ -91,7 +93,8 @@       , mtl       , criterion       , resource-pool-      , rethinkdb-client-driver >= 0.0.11+      , rethinkdb-client-driver >= 0.0.19+      , network-uri       , text  @@ -116,7 +119,7 @@       , inflections       , mtl       , resource-pool-      , rethinkdb-client-driver >= 0.0.11+      , rethinkdb-client-driver >= 0.0.19       , scrypt       , stm       , text
benchmark/Benchmark.hs view
@@ -18,6 +18,8 @@ import           System.Environment import           System.IO.Unsafe +import           Network.URI+ import           Criterion.Main  import           Avers@@ -39,29 +41,29 @@     }  -databaseConfig :: IO (Text, Text)+databaseConfig :: IO URI databaseConfig = do-    host     <- fromMaybe "localhost" <$> lookupEnv "RETHINKDB"-    database <- fromMaybe "test" <$> lookupEnv "DATABASE"-    return (T.pack host, T.pack database)+    uri <- fromMaybe "//localhost/test" <$> lookupEnv "RETHINKDB"+    return $ fromJust $ parseRelativeReference uri  -mkBenchmarkHandle :: IO AversState+mkBenchmarkHandle :: IO Handle mkBenchmarkHandle = do-    (host, db) <- databaseConfig-    let config = AversConfig host db undefined [SomeObjectType dummyObjectType] (\_ _ -> return ())-    newState config+    dbURI <- databaseConfig+    let config = Config dbURI undefined [SomeObjectType dummyObjectType] (\_ _ -> return ())+    Right h <- newState config+    return h  -{-# NOINLINE aversStateRef #-}-aversStateRef :: IORef AversState-aversStateRef = unsafePerformIO $ do+{-# NOINLINE handleRef #-}+handleRef :: IORef Handle+handleRef = unsafePerformIO $ do     newIORef =<< mkBenchmarkHandle   benchAvers :: Avers a -> IO () benchAvers m = do-    h <- readIORef aversStateRef+    h <- readIORef handleRef     void $ evalAvers h m  
src/Avers.hs view
@@ -61,8 +61,8 @@   , lookupObjectType    , AversError(..)-  , AversConfig(..)-  , AversState+  , Config(..)+  , Handle   , newState   , strErr   , parseValueAs
src/Avers/Storage.hs view
@@ -21,6 +21,7 @@ import           Control.Monad.State import           Control.Monad.Except +import           Data.Pool import           Data.Char import           Data.Monoid import           Data.Maybe@@ -467,7 +468,10 @@ saveBlobContent :: Blob -> BL.ByteString -> Avers () saveBlobContent Blob{..} content = do     cfg <- gets config-    liftIO $ (putBlob cfg) blobId blobContentType content+    res <- liftIO $ (putBlob cfg) blobId blobContentType content+    case res of+        Left e -> throwError e+        Right _ -> return ()   saveSession :: Session -> Avers ()@@ -649,7 +653,8 @@ createTable :: Text -> [SomeIndex] -> Avers () createTable name indices = do     let table = R.Table Nothing $ R.lift name-    db <- fmap R.Database $ fmap R.lift $ fmap databaseName $ gets config+    pool <- gets databaseHandlePool+    db <- liftIO $ withResource pool $ \handle -> pure $ R.handleDatabase handle      tables <- runQuery $ R.ListTables db     when (name `V.notElem` tables) $ do
src/Avers/Types.hs view
@@ -7,6 +7,9 @@  module Avers.Types where ++import           Safe+ import           Control.Applicative  import           Control.Monad.Except@@ -25,6 +28,7 @@ import qualified Data.Map  as M  import           Data.Monoid+import           Data.Maybe import           Data.Char  import           Data.Attoparsec.Text@@ -34,6 +38,8 @@ import           Data.Aeson (Value(String)) import           Data.Aeson.Types (parseEither) +import           Network.URI+ import qualified Database.RethinkDB       as R import           Database.RethinkDB.TH @@ -499,21 +505,18 @@   -- | Configuration of the 'Avers' monad.-data AversConfig = AversConfig--    { databaseHost :: !Text-      -- ^ The hostname where RethinkDB is running. The port is currently not-      -- configurable.+data Config = Config -    , databaseName :: !Text-      -- ^ RethinkDB supports multiple databases. This is the name of the one-      -- which should be used.+    { databaseURI :: !URI+      -- ^ 'URI' which describes the connection details to the RethinkDB+      -- database. The 'URI' *MUST* include at least the hostname ('uriRegName')+      -- and database name ('uriPath' without the leading slash). The port+      -- ('uriPort') and credentials ('uriUserInfo') *MAY* be left empty.+      -- in that case the default port will be used. -    , putBlob :: BlobId -> Text -> ByteString -> IO ()+    , putBlob :: BlobId -> Text -> ByteString -> IO (Either AversError ())       -- ^ Function which saves the given blob in the blob store. This can be-      -- the local filesystem or an external services such as Amazon S3.-      ---      -- TODO: Propagate errors back to the caller.+      -- the local filesystem or an external service such as Amazon S3.      , objectTypes :: ![SomeObjectType]       -- ^ All the object types which Avers knows about.@@ -523,9 +526,30 @@       -- a measurement.     } +databaseHost :: Config -> Either AversError Text+databaseHost Config{..} = maybe (Left $ AversError "databaseHost: not given") Right $ do+    auth <- uriAuthority databaseURI+    return $ T.pack $ uriRegName auth -data AversState = AversState-    { config :: !AversConfig+databasePort :: Config -> Int+databasePort Config{..} = fromMaybe R.defaultPort $ do+    auth <- uriAuthority databaseURI+    readMay $ uriPort auth++databaseAuth :: Config -> Maybe Text+databaseAuth Config{..} = do+    auth <- uriAuthority databaseURI+    return $ T.pack $ uriUserInfo auth++extractDatabaseName :: Config -> Either AversError Text+extractDatabaseName Config{..} = case tail $ uriPath $ databaseURI of+    "" -> Left $ AversError "databaseName: not given"+    db -> Right $ T.pack db++++data Handle = Handle+    { config :: !Config       -- ^ A reference to the config, just in case we need it.      , databaseHandlePool :: !(Pool R.Handle)@@ -538,21 +562,25 @@   -newDatabaseHandlePool :: AversConfig -> IO (Pool R.Handle)-newDatabaseHandlePool AversConfig{..} =-    createPool create destroy numStripes idleTime maxResources+newDatabaseHandlePool :: Config -> Text -> ExceptT AversError IO (Pool R.Handle)+newDatabaseHandlePool config db = do+    host <- ExceptT $ pure $ databaseHost config+    let port = databasePort config+    let mbAuth = databaseAuth config +    lift $ createPool (create host port mbAuth) destroy numStripes idleTime maxResources+   where-    create = do+    create host port mbAuth = do         putStrLn $ mconcat             [ "Creating a new RethinkDB handle to "-            , T.unpack databaseHost-            , ":28015"+            , T.unpack host+            , show port             , " database "-            , T.unpack databaseName+            , T.unpack db             ] -        R.newHandle databaseHost 28015 Nothing (R.Database (R.lift databaseName))+        R.newHandle host port mbAuth (R.Database (R.lift db))      destroy handle = do         putStrLn "Closing RethinkDB handle"@@ -563,17 +591,21 @@     maxResources = 10  -newState :: AversConfig -> IO AversState-newState config = do-    AversState-        <$> pure config-        <*> newDatabaseHandlePool config-        <*> newTVarIO M.empty+newState :: Config -> IO (Either AversError Handle)+newState config = runExceptT $ do+    databaseName <- ExceptT $ pure $ extractDatabaseName config+    databaseHandlePool <- newDatabaseHandlePool config databaseName+    recentRevisionCache <- lift $ newTVarIO M.empty +    Handle+        <$> (pure config)+        <*> (pure databaseHandlePool)+        <*> (pure recentRevisionCache) + newtype Avers a = Avers-    { runAvers :: StateT AversState (ExceptT AversError IO) a-    } deriving (Functor, Applicative, Monad, MonadIO, MonadError AversError, MonadState AversState)+    { runAvers :: StateT Handle (ExceptT AversError IO) a+    } deriving (Functor, Applicative, Monad, MonadIO, MonadError AversError, MonadState Handle)  class (Monad m) => MonadAvers m where     liftAvers :: Avers a -> m a@@ -584,7 +616,7 @@ instance MonadAvers m => MonadAvers (StateT s m) where     liftAvers = lift . liftAvers -evalAvers :: AversState -> Avers a -> IO (Either AversError a)+evalAvers :: Handle -> Avers a -> IO (Either AversError a) evalAvers h m = runExceptT $ evalStateT (runAvers m) h