{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
module Haxl.Core.RequestStore
( BlockedFetches(..)
, RequestStore
, isEmpty
, noRequests
, addRequest
, contents
, ReqCountMap(..)
, emptyReqCounts
, filterRCMap
, getMapFromRCMap
, addToCountMap
, subFromCountMap
) where
#if __GLASGOW_HASKELL__ <= 708
import Control.Applicative ((<$>))
#endif
import Haxl.Core.DataSource
import Data.Map (Map)
import qualified Data.Map.Strict as Map
import Data.Proxy
import Data.Text (Text)
import Data.Typeable
import Unsafe.Coerce
newtype RequestStore u = RequestStore (Map TypeRep (BlockedFetches u))
data BlockedFetches u =
forall r. (DataSource u r) => BlockedFetches [BlockedFetch r]
isEmpty :: RequestStore u -> Bool
isEmpty (RequestStore m) = Map.null m
noRequests :: RequestStore u
noRequests = RequestStore Map.empty
addRequest
:: forall u r. (DataSource u r)
=> BlockedFetch r -> RequestStore u -> RequestStore u
addRequest bf (RequestStore m) =
RequestStore $ Map.insertWith combine ty (BlockedFetches [bf]) m
where
combine :: BlockedFetches u -> BlockedFetches u -> BlockedFetches u
combine _ (BlockedFetches bfs)
| typeOf1 (getR bfs) == ty = BlockedFetches (unsafeCoerce bf:bfs)
| otherwise = error "RequestStore.insert"
getR :: [BlockedFetch r1] -> r1 a
getR _ = undefined
ty :: TypeRep
!ty = typeOf1 (undefined :: r a)
contents :: RequestStore u -> [BlockedFetches u]
contents (RequestStore m) = Map.elems m
newtype ReqCountMap = ReqCountMap (Map Text (Map TypeRep Int))
deriving (Show)
emptyReqCounts :: ReqCountMap
emptyReqCounts = ReqCountMap Map.empty
addToCountMap
:: forall (r :: * -> *). (DataSourceName r, Typeable r)
=> Proxy r
-> Int
-> ReqCountMap
-> ReqCountMap
addToCountMap = updateCountMap (+)
subFromCountMap
:: forall (r :: * -> *). (DataSourceName r, Typeable r)
=> Proxy r
-> Int
-> ReqCountMap
-> ReqCountMap
subFromCountMap = updateCountMap (-)
updateCountMap
:: forall (r :: * -> *). (DataSourceName r, Typeable r)
=> (Int -> Int -> Int)
-> Proxy r
-> Int
-> ReqCountMap
-> ReqCountMap
updateCountMap op p n (ReqCountMap m) = ReqCountMap $ Map.insertWith
(flip (Map.unionWith op))
(dataSourceName p) (Map.singleton ty n)
m
where
ty :: TypeRep
!ty = typeOf1 (undefined :: r a)
filterRCMap :: ReqCountMap -> ReqCountMap
filterRCMap (ReqCountMap m) = ReqCountMap $
Map.filter ((> 0) . Map.size) (Map.filter (> 0) <$> m)
getMapFromRCMap :: ReqCountMap -> Map Text (Map TypeRep Int)
getMapFromRCMap r
| ReqCountMap m <- filterRCMap r = m