montage-0.1: Network/Riak/Montage/Backend.hs
module Network.Riak.Montage.Backend where
import Prelude hiding (catch)
import Control.Monad (void, when)
import Control.Exception (catch, throw, SomeException(..))
import Control.Concurrent (threadDelay)
import Data.ByteString.Lazy as L
import Network.Riak.Types
import Network.Riak.Value.Resolvable (getWithLength, put, delete)
import Network.StatsWeb (Stats, incCounter)
import Network.Riak.Montage.Types
import Data.Conduit.Pool (withResource)
maxRetries :: Int
maxRetries = 3
-- We can't actually put in the type signatures below, see
-- http://www.haskell.org/haskellwiki/Type_families#Injectivity.2C_type_inference.2C_and_ambiguity
retryOperation :: IO a -> IO a
retryOperation op =
retryOperation' 0
where
--retryOperation' :: IO a -> Int -> IO a
retryOperation' retries = catch op (handleError retries)
--handleError :: (Exception e) => Int -> e -> IO a
handleError retries e = case retries > maxRetries of
True -> throw (e :: SomeException)
False -> do
threadDelay $ 100000 * retries
retryOperation' $ retries + 1
doGet :: (MontageRiakValue r) => Stats -> Bucket -> Key -> PoolChooser -> IO (RiakResponse r)
doGet stats buck key chooser' = do
res <- retryOperation $ withResource (chooser' buck) $ \c -> getWithLength c buck key Default
case res of
Just ((resolved, siblings), v) -> do
let resolvedLength = L.length $ riakSerialize resolved
when (siblings > 10) $ incCounter "requests.many.siblings" stats
when (resolvedLength > 1097152) $ incCounter "requests.big" stats
return $ Just (resolved, v, Just siblings)
Nothing -> return Nothing
doPut :: (MontageRiakValue r) => Bucket -> Key -> VectorClock -> RiakRecord r -> PoolChooser -> IO (RiakResponse r)
doPut buck key mvc rec chooser' = do
let riakvc = fmap VClock mvc
res <- retryOperation $ withResource (chooser' buck) $ \c -> (fmap Just $ put c buck key riakvc rec (Just 1) Default Default)
return $ fmap (\(r, v) -> (r, v, Nothing)) res
doDelete :: (MontageRiakValue a) => Bucket -> Key -> PoolChooser -> IO (RiakResponse a)
doDelete buck key chooser' = do
void $ retryOperation $ withResource (chooser' buck) $ (\c -> delete c buck key Default >> return Nothing)
return Nothing