packages feed

liszt-0.2: src/Database/Liszt.hs

{-# LANGUAGE LambdaCase #-}
module Database.Liszt (
    openLiszt,
    closeLiszt,
    withLiszt,
    LisztHandle,
    -- * Writer interface
    Key,
    Tag,
    Transaction,
    clear,
    insert,
    insertTagged,
    insertRaw,
    commit,
    commitFile,
    -- * Local reader
    RawPointer,
    count,
    fetchRange,
    fetchPayload,
    -- * Remote reader
    Offset(..),
    Request(..),
    defRequest,
    Connection,
    withConnection,
    fetch,
    LisztError(..)
    ) where

import Control.Monad.IO.Class
import Database.Liszt.Internal
import Database.Liszt.Network
import Database.Liszt.Tracker
import Data.Winery

-- | Commit a 'Transaction' to a file.
commitFile :: (MonadIO m) => FilePath -> Transaction a -> m a
commitFile path m = liftIO $ withLiszt path $ \h -> commit h m

-- | Insert a value.
insert :: Serialise a => Key -> a -> Transaction ()
insert k v = insertRaw k mempty (toEncoding v)
{-# INLINE insert #-}

-- | Insert a value with a tag (e.g. timestamp).
-- Tags can be used to perform `WineryTag` query.
-- Tag values should be monotonically increasing but this is not checked.
insertTagged :: (Serialise t, Serialise a) => Key -> t -> a -> Transaction ()
insertTagged k t v = insertRaw k (toEncoding t) (toEncoding v)
{-# INLINE insertTagged #-}

-- | The number of entries in the stream
count :: MonadIO m => LisztHandle -> Key -> m Int
count h k = liftIO $ do
  root <- fetchRoot h
  maybe 0 spineLength <$> lookupSpine h k root

fetchRange :: MonadIO m => LisztHandle -> Key -> Int -> Int -> m [(Int, Tag, RawPointer)]
fetchRange h key i_ j_ = liftIO $ do
  root <- fetchRoot h
  lookupSpine h key root >>= \case
    Nothing -> return []
    Just spine -> do
      let len = spineLength spine
      let normalise x
            | x < 0 = min (len - 1) $ max 0 $ len + x
            | otherwise = min (len - 1) x
      let j = normalise j_
      let i = normalise i_
      spine' <- dropSpine h (len - j - 1) spine
      result <- takeSpine h (j - i + 1) spine' []
      return [(k, t, rp) | (k, (t, rp)) <- zip [i..] result]