Added key and value types
Getty Ritter
8 years ago
43 | 43 |
createEphemeralDb ls = EDB (M.fromList [ (encode k, encode v) | (k, v) <- ls ])
|
44 | 44 |
|
45 | 45 |
-- | Run a 'Tansu' operation with an empty in-memory table.
|
46 | |
withNewEphemeralDb :: (TansuDb -> IO a) -> IO a
|
| 46 |
withNewEphemeralDb :: (TansuDb k v -> IO a) -> IO a
|
47 | 47 |
withNewEphemeralDb = withEphemeralDb $ EDB M.empty
|
48 | 48 |
|
49 | 49 |
-- | Run a 'Tansu' operation with an existing in-memory table.
|
50 | |
withEphemeralDb :: EphemeralDb -> (TansuDb -> IO a) -> IO a
|
| 50 |
withEphemeralDb :: EphemeralDb -> (TansuDb k v -> IO a) -> IO a
|
51 | 51 |
withEphemeralDb init comp = do
|
52 | 52 |
lock <- newMVar ()
|
53 | 53 |
table <- newIORef (fromEDB init)
|
46 | 46 |
-- @.lock@ file in the specified directory, but note that
|
47 | 47 |
-- file locking is not a guaranteed way of ensuring exclusion,
|
48 | 48 |
-- and that the files themselves are not locked in any way.
|
49 | |
withFilesystemDb :: FilePath -> (TansuDb -> IO a) -> IO a
|
| 49 |
withFilesystemDb :: FilePath -> (TansuDb k v -> IO a) -> IO a
|
50 | 50 |
withFilesystemDb path comp = do
|
51 | 51 |
createDirectoryIfMissing True path
|
52 | 52 |
comp $ TansuDb { dbSet = filePathSet path
|
23 | 23 |
-- should treat this as an abstract type, but the full definition
|
24 | 24 |
-- is exposed by the "Database.Tansu.Internal" module so that
|
25 | 25 |
-- other libraries can implement new storage backends.
|
26 | |
data TansuDb = TansuDb
|
| 26 |
--
|
| 27 |
-- A given instantiation of the database will have
|
| 28 |
data TansuDb k v = TansuDb
|
27 | 29 |
{ dbSet :: ByteString -> ByteString -> IO (Either TansuError ())
|
28 | 30 |
, dbGet :: ByteString -> IO (Either TansuError ByteString)
|
29 | 31 |
, dbDel :: ByteString -> IO (Either TansuError ())
|
| 1 |
{-# LANGUAGE RankNTypes #-}
|
| 2 |
|
1 | 3 |
module Database.Tansu ( -- * The 'Tansu' monad
|
2 | 4 |
Tansu
|
3 | 5 |
, TansuDb
|
|
24 | 26 |
)
|
25 | 27 |
import Database.Tansu.Internal
|
26 | 28 |
|
27 | |
type TansuM a = ReaderT TansuDb (ExceptionT TansuError IO) a
|
| 29 |
type TansuM k v a = ReaderT (TansuDb k v) (ExceptionT TansuError IO) a
|
28 | 30 |
|
29 | 31 |
-- | The 'Tansu' type is a monad which represents some sequence
|
30 | 32 |
-- of 'get' and 'set' operations. Ideally, backends should
|
31 | 33 |
-- make some guarantee about the atomicity of a given
|
32 | 34 |
-- 'Tansu' computation, but you should consult the documentation
|
33 | 35 |
-- about a given backend to make sure that holds.
|
34 | |
newtype Tansu k v a = Tansu { runTansu :: TansuM a }
|
| 36 |
newtype Tansu k v a = Tansu { runTansu :: TansuM k v a }
|
35 | 37 |
|
36 | 38 |
instance Functor (Tansu k v) where
|
37 | 39 |
fmap f (Tansu t) = Tansu (fmap f t)
|
|
94 | 96 |
-- | Given a storage backend and a 'Tansu' computation, execute the
|
95 | 97 |
-- sequence of 'get' and 'set' commands and produce either the value
|
96 | 98 |
-- or the error encountered while running the computation.
|
97 | |
run :: TansuDb -> Tansu k v a -> IO (Either TansuError a)
|
| 99 |
run :: TansuDb k v -> Tansu k v a -> IO (Either TansuError a)
|
98 | 100 |
run db (Tansu comp) =
|
99 | 101 |
dbRunTransaction db (runExceptionT (runReaderT db comp))
|
68 | 68 |
del :: (Serialize k) => k -> Tansu k v ()
|
69 | 69 |
|
70 | 70 |
-- run a Tansu computation
|
71 | |
run :: TansuDb -> Tansu k v a -> IO (Either TansuError a)
|
| 71 |
run :: TansuDb k v -> Tansu k v a -> IO (Either TansuError a)
|
72 | 72 |
~~~
|
73 | 73 |
|
74 | 74 |
A value of type `TansuDb` should be supplied by a _backend_, which can
|
|
80 | 80 |
backends can be simply implemented separately from the core `tansu`
|
81 | 81 |
library, and backends can be easily swapped out as desired.
|
82 | 82 |
|
| 83 |
## Tansu Backends
|
| 84 |
|
| 85 |
[...]
|
| 86 |
|
83 | 87 |
## About the Name
|
84 | 88 |
|
85 | 89 |
A _tansu_ is a kind of
|
13 | 13 |
putStrLn "Testing ephemeral db"
|
14 | 14 |
withNewEphemeralDb sample
|
15 | 15 |
|
16 | |
sample :: TansuDb -> IO ()
|
| 16 |
sample :: TansuDb String String -> IO ()
|
17 | 17 |
sample db = do
|
18 | 18 |
putStrLn "Populating test database"
|
19 | 19 |
run db $ do
|