Safe Haskell | None |
---|
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.
:: 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
Persisted | |
|
data EZCouchException Source
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
ReadOptions | |
|
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
(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.
(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
toJSON
function that accepts any type which is an instance ofData
. - If your compiler has support for the
DeriveGeneric
andDefaultSignatures
language extensions (GHC 7.2 and newer),toJSON
will have a default generic implementation.
To use the latter option, simply add a deriving
clause to your
datatype and declare a Generic
ToJSON
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
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 usemzero
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
fromJSON
function that parses to any type which is an instance ofData
. - If your compiler has support for the
DeriveGeneric
andDefaultSignatures
language extensions,parseJSON
will have a default generic implementation.
To use this, simply add a deriving
clause to your datatype and
declare a Generic
FromJSON
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