packages feed

shikumi-cache-0.1.0.0: src/Shikumi/Cache/Backend/Memory.hs

-- | The in-memory cache backend (EP-6): a process-local @STM@ map from the hex
-- cache key to a 'CachedResponse'. It stores the Haskell value directly (no
-- serialization), so it needs no JSON instances for the baikai 'Response' graph.
-- Build the store with 'newMemoryCache' and discharge the 'Cache' effect with
-- 'runCacheMemory'.
module Shikumi.Cache.Backend.Memory
  ( MemoryCache,
    newMemoryCache,
    runCacheMemory,
  )
where

import Control.Concurrent.STM (TVar, modifyTVar', newTVarIO)
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as Map
import Data.Text (Text)
import Effectful (Eff, (:>))
import Effectful.Concurrent (Concurrent)
import Effectful.Concurrent.STM (atomically, readTVarIO)
import Effectful.Dispatch.Dynamic (interpret)
import Shikumi.Cache (Cache (..), CacheKey (unCacheKey), CachedResponse)

-- | The in-memory store: a 'TVar' over a map keyed by the hex cache key.
type MemoryCache = TVar (Map Text CachedResponse)

-- | Create a fresh, empty in-memory cache.
newMemoryCache :: IO MemoryCache
newMemoryCache = newTVarIO Map.empty

-- | Discharge the 'Cache' effect against an in-memory store.
runCacheMemory :: (Concurrent :> es) => MemoryCache -> Eff (Cache : es) a -> Eff es a
runCacheMemory tv = interpret $ \_ -> \case
  LookupCache k -> Map.lookup (unCacheKey k) <$> readTVarIO tv
  StoreCache k v -> atomically (modifyTVar' tv (Map.insert (unCacheKey k) v))