| Safe Haskell | None |
|---|
EZCouch
Contents
Description
EZCouch is a library which takes a mission of bringing the topmost level of abstraction for working with CouchDB from Haskell. It abstracts away from loose concepts of this database and brings a strict static API over standard ADTs.
- create :: (MonadAction m, Doc a) => a -> m (Persisted a)
- createMultiple :: (MonadAction m, Doc a) => [a] -> m [Persisted a]
- readOne :: (MonadAction m, Doc a, ToJSON k) => ReadOptions a k -> m (Maybe (Persisted a))
- readMultiple :: (MonadAction m, Doc a, ToJSON k) => ReadOptions a k -> m [Persisted a]
- readExists :: (MonadAction m, Doc a, ToJSON k, FromJSON k) => ReadOptions a k -> m [(k, Bool)]
- readIds :: (MonadAction m, Doc a) => ReadOptions a Text -> m [Text]
- readKeys :: (MonadAction m, Doc a, ToJSON k, FromJSON k) => ReadOptions a k -> m [k]
- readCount :: (MonadAction m, Doc a, ToJSON k, FromJSON k) => ReadOptions a k -> m Int
- update :: (MonadAction m, Doc a) => Persisted a -> m (Persisted a)
- updateMultiple :: (MonadAction m, Doc a) => [Persisted a] -> m [Persisted a]
- delete :: (MonadAction m, Doc a) => Persisted a -> m ()
- deleteMultiple :: (MonadAction m, Doc a) => [Persisted a] -> m ()
- readTime :: MonadAction m => m UTCTime
- createOrUpdateView :: (Doc a, MonadAction m) => Text -> Maybe Text -> View a -> m ()
- inIsolation :: MonadAction m => Int -> Text -> m a -> m (Maybe a)
- data Persisted a = Persisted {
- persistedId :: Text
- persistedRev :: Text
- persistedValue :: a
- data EZCouchException
- newtype View a = View {}
- data ReadOptions a k = ReadOptions {
- readOptionsKeys :: Maybe [k]
- readOptionsView :: Maybe (View a)
- readOptionsDescending :: Bool
- readOptionsLimit :: Maybe Int
- readOptionsSkip :: Int
- readOptions :: ReadOptions a Text
- data ConnectionSettings = ConnectionSettings {}
- defaultPort :: Int
- tryOperation :: MonadAction m => m a -> m (Maybe a)
- class (MonadBaseControl IO m, MonadResource m, MonadReader (ConnectionSettings, Manager) m) => MonadAction m
- run :: (MonadIO m, MonadBaseControl IO m, MonadThrow m, MonadUnsafeIO m) => t -> ReaderT (t, Manager) (ResourceT m) a -> m a
- runWithManager :: t1 -> t -> ReaderT (t, t1) m a -> m a
- class (ToJSON a, FromJSON a) => Doc a where
- class ToJSON a where
- class FromJSON a where
CRUD Monadic Functions for Working with Records
All monadic functions are split into CRUD categories. The functions with a Multiple suffix are better alternatives for performing multiple operations at once.
Creating
create :: (MonadAction m, Doc a) => a -> m (Persisted a)Source
createMultiple :: (MonadAction m, Doc a) => [a] -> m [Persisted a]Source
Reading
All reading actions accept a ReadOptions parameter which specifies how filtering and ordering should go.
readOne :: (MonadAction m, Doc a, ToJSON k) => ReadOptions a k -> m (Maybe (Persisted a))Source
readMultiple :: (MonadAction m, Doc a, ToJSON k) => ReadOptions a k -> m [Persisted a]Source
readExists :: (MonadAction m, Doc a, ToJSON k, FromJSON k) => ReadOptions a k -> m [(k, Bool)]Source
readIds :: (MonadAction m, Doc a) => ReadOptions a Text -> m [Text]Source
readKeys :: (MonadAction m, Doc a, ToJSON k, FromJSON k) => ReadOptions a k -> m [k]Source
readCount :: (MonadAction m, Doc a, ToJSON k, FromJSON k) => ReadOptions a k -> m IntSource
Updating
updateMultiple :: (MonadAction m, Doc a) => [Persisted a] -> m [Persisted a]Source
Deleting
delete :: (MonadAction m, Doc a) => Persisted a -> m ()Source
deleteMultiple :: (MonadAction m, Doc a) => [Persisted a] -> m ()Source
Server Time
readTime :: MonadAction m => m UTCTimeSource
Current time according to server.
Working with Views
Transactions
CouchDB doesn't provide a way to do traditional locking-based transactions, as it applies an Optimistic Concurrency Control strategy (http://en.wikipedia.org/wiki/Optimistic_concurrency_control). EZCouch approaches the issue by abstracting over it.
Arguments
| :: MonadAction m | |
| => Int | A timeout in seconds. If after reaching it a conflicting isolation marker still exists in the db, it gets considered to be zombie (probably caused by a client interruption). The marker gets deleted and the current action gets executed. |
| -> Text | A unique isolation identifier. It's a common practice to provide a |
| -> m a | The action to protect. Nothing of it will be executed if an isolation with the same id is already running. |
| -> m (Maybe a) | Either the action's result or |
Protect an action from being executed on multiple clients. Can be used to create transactions in a preemptive manner, i.e. instead of performing some actions and rolling back on transaction validation failure it does validation based on the provided identifier prior to actually executing the transaction. This function however does not provide you with atomicity guarantees (http://en.wikipedia.org/wiki/Atomicity_(database_systems)), as it does not rollback in case of client-interrupt - it's up to your algorithms to handle those cases.
Types
Constructors
| Persisted | |
Fields
| |
data EZCouchException Source
Constructors
| ParsingException Text | A response from CouchDB could not be parsed. |
| OperationException Text | An operation failed, e.g. a document couldn't be created or deleted. |
| ServerException Text | E.g., server provided an unexpected response |
| ConnectionException Text |
Identifies a Couch's design and view. The design name is implicitly resolved from the type parameter a and becomes the name of this type. The view name however must be specified explicitly.
data ReadOptions a k Source
Constructors
| ReadOptions | |
Fields
| |
Instances
| Typeable2 ReadOptions | |
| Eq k => Eq (ReadOptions a k) | |
| (Data a, Data k) => Data (ReadOptions a k) | |
| Ord k => Ord (ReadOptions a k) | |
| Show k => Show (ReadOptions a k) |
data ConnectionSettings Source
Constructors
| ConnectionSettings | |
Fields | |
Instances
| (MonadResource m, MonadBaseControl IO m) => MonadAction (ReaderT (ConnectionSettings, Manager) m) |
Helpers
tryOperation :: MonadAction m => m a -> m (Maybe a)Source
Return Nothing if an action throws an OperationException or Just its result otherwise.
This is only useful for a modifying actions (Create, Update, Delete).
Execution Monad
class (MonadBaseControl IO m, MonadResource m, MonadReader (ConnectionSettings, Manager) m) => MonadAction m Source
All EZCouch operations are performed in this monad.
Instances
| (MonadResource m, MonadBaseControl IO m) => MonadAction (ReaderT (ConnectionSettings, Manager) m) |
run :: (MonadIO m, MonadBaseControl IO m, MonadThrow m, MonadUnsafeIO m) => t -> ReaderT (t, Manager) (ResourceT m) a -> m aSource
runWithManager :: t1 -> t -> ReaderT (t, t1) m a -> m aSource
Classes which records should implement
Aeson re-exports
class ToJSON a where
A type that can be converted to JSON.
An example type and instance:
{-# LANGUAGE OverloadedStrings #-}
data Coord { x :: Double, y :: Double }
instance ToJSON Coord where
toJSON (Coord x y) = object ["x" .= x, "y" .= y]
Note the use of the OverloadedStrings language extension which enables
Text values to be written as string literals.
Instead of manually writing your ToJSON instance, there are three options
to do it automatically:
- Data.Aeson.TH provides template-haskell functions which will derive an instance at compile-time. The generated instance is optimized for your type so will probably be more efficient than the following two options:
- Data.Aeson.Generic provides a generic
toJSONfunction that accepts any type which is an instance ofData. - If your compiler has support for the
DeriveGenericandDefaultSignatureslanguage extensions (GHC 7.2 and newer),toJSONwill have a default generic implementation.
To use the latter option, simply add a deriving clause to your
datatype and declare a GenericToJSON instance for your datatype without giving a
definition for toJSON.
For example the previous example can be simplified to just:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
data Coord { x :: Double, y :: Double } deriving Generic
instance ToJSON Coord
Instances
class FromJSON a where
A type that can be converted from JSON, with the possibility of failure.
When writing an instance, use empty, mzero, or fail to make a
conversion fail, e.g. if an Object is missing a required key, or
the value is of the wrong type.
An example type and instance:
{-# LANGUAGE OverloadedStrings #-}
data Coord { x :: Double, y :: Double }
instance FromJSON Coord where
parseJSON (Object v) = Coord <$>
v .: "x" <*>
v .: "y"
-- A non-Object value is of the wrong type, so use mzero to fail.
parseJSON _ = mzero
Note the use of the OverloadedStrings language extension which enables
Text values to be written as string literals.
Instead of manually writing your FromJSON instance, there are three options
to do it automatically:
- Data.Aeson.TH provides template-haskell functions which will derive an instance at compile-time. The generated instance is optimized for your type so will probably be more efficient than the following two options:
- Data.Aeson.Generic provides a generic
fromJSONfunction that parses to any type which is an instance ofData. - If your compiler has support for the
DeriveGenericandDefaultSignatureslanguage extensions,parseJSONwill have a default generic implementation.
To use this, simply add a deriving clause to your datatype and
declare a GenericFromJSON instance for your datatype without giving a definition
for parseJSON.
For example the previous example can be simplified to just:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
data Coord { x :: Double, y :: Double } deriving Generic
instance FromJSON Coord
Instances