module Haxl.Core.DataCache
( DataCache(..)
, SubCache(..)
, emptyDataCache
, insert
, insertNotShowable
, insertWithShow
, lookup
, showCache
) where
import Data.Hashable
import Prelude hiding (lookup)
import Unsafe.Coerce
import qualified Data.HashMap.Strict as HashMap
import Data.Typeable
import Data.Maybe
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative ((<$>))
#endif
import Control.Exception
import Haxl.Core.Types
insert
:: (Hashable (req a), Typeable (req a), Eq (req a), Show (req a), Show a)
=> req a
-> res a
-> DataCache res
-> DataCache res
insert = insertWithShow show show
insertWithShow
:: (Hashable (req a), Typeable (req a), Eq (req a))
=> (req a -> String)
-> (a -> String)
-> req a
-> res a
-> DataCache res
-> DataCache res
insertWithShow showRequest showResult req result (DataCache m) =
DataCache $
HashMap.insertWith fn (typeOf req)
(SubCache showRequest showResult (HashMap.singleton req result)) m
where
fn (SubCache _ _ new) (SubCache showReq showRes old) =
SubCache showReq showRes (unsafeCoerce new `HashMap.union` old)
insertNotShowable
:: (Hashable (req a), Typeable (req a), Eq (req a))
=> req a
-> res a
-> DataCache res
-> DataCache res
insertNotShowable = insertWithShow notShowable notShowable
notShowable :: a
notShowable = error "insertNotShowable"
lookup
:: Typeable (req a)
=> req a
-> DataCache res
-> Maybe (res a)
lookup req (DataCache m) =
case HashMap.lookup (typeOf req) m of
Nothing -> Nothing
Just (SubCache _ _ sc) ->
unsafeCoerce (HashMap.lookup (unsafeCoerce req) sc)
showCache
:: DataCache ResultVar
-> IO [(TypeRep, [(String, Either SomeException String)])]
showCache (DataCache cache) = mapM goSubCache (HashMap.toList cache)
where
goSubCache
:: (TypeRep,SubCache ResultVar)
-> IO (TypeRep,[(String, Either SomeException String)])
goSubCache (ty, SubCache showReq showRes hmap) = do
elems <- catMaybes <$> mapM go (HashMap.toList hmap)
return (ty, elems)
where
go (req, rvar) = do
maybe_r <- tryReadResult rvar
case maybe_r of
Nothing -> return Nothing
Just (Left e) -> return (Just (showReq req, Left e))
Just (Right result) ->
return (Just (showReq req, Right (showRes result)))