glue-core-0.7.0: src/Glue/Caching.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | Module supporting the caching of a service.
module Glue.Caching
( cacheWithBasic
, cacheWithMulti
) where
import Data.Hashable (Hashable)
import qualified Data.HashMap.Strict as M
import qualified Data.HashSet as S
import Glue.Types
-- | Caching of a 'BasicService' instance, that defers to external functions for the actual caching.
-- Note: Values within @m@ will be lost for calls that hit the cache.
cacheWithBasic
:: Monad m
=> (a -> m (Maybe b))
-- ^ Cache lookup function, used before potentially invoking the fallback service.
-> (a -> b -> m ())
-- ^ Cache write function, used after invoking the fallback service to populate the cache.
-> BasicService m a b
-- ^ The service to cache.
-> BasicService m a b
cacheWithBasic lookupWith insertWith service =
let fallback request = do
result <- service request
insertWith request result
pure result
cachedService request = do
fromCache <- lookupWith request
maybe (fallback request) pure fromCache
in cachedService
-- | Caching of a 'MultiGetService' instance, that defers to external functions for the actual caching.
-- Partial responses will result in partial fallback calls that get just the missing keys.
-- Values within @m@ will be lost for calls that hit the cache.
cacheWithMulti
:: (Monad m, Hashable a)
=> (MultiGetRequest a -> m (MultiGetResponse a b))
-- ^ Cache lookup function, used before potentially invoking the fallback service.
-> (MultiGetResponse a b -> m ())
-- ^ Cache write function, used after invoking the fallback service to populate the cache.
-> MultiGetService m a b
-- ^ The service to cache.
-> MultiGetService m a b
cacheWithMulti lookupWith insertWith service =
let fallback request = do
result <- service request
insertWith result
pure result
cachedService request = do
fromCache <- lookupWith request
let uncachedKeys = S.difference request (S.fromList $ M.keys fromCache)
if S.null uncachedKeys
then pure fromCache
else M.union fromCache <$> fallback uncachedKeys
in cachedService