packages feed

calamity-0.1.4.2: src/Calamity/Cache/InMemory.hs

-- | A 'Cache' handler that operates in memory
module Calamity.Cache.InMemory
    ( runCacheInMemory ) where

import           Calamity.Cache.Eff
import           Calamity.Internal.BoundedStore
import qualified Calamity.Internal.SnowflakeMap as SM
import           Calamity.Internal.Utils
import           Calamity.Types.Model.Channel
import           Calamity.Types.Model.Guild
import           Calamity.Types.Model.User
import           Calamity.Types.Snowflake

import           Control.Lens
import           Control.Monad.State.Strict

import           Data.Default.Class
import           Data.Foldable
import qualified Data.HashSet                   as LS
import           Data.IORef

import           GHC.Generics

import qualified Polysemy                       as P
import qualified Polysemy.AtomicState           as P

data Cache = Cache
  { user              :: Maybe User
  , guilds            :: SM.SnowflakeMap Guild
  , dms               :: SM.SnowflakeMap DMChannel
  , channels          :: SM.SnowflakeMap GuildChannel
  , users             :: SM.SnowflakeMap User
  , unavailableGuilds :: LS.HashSet (Snowflake Guild)
  , messages          :: BoundedStore Message
  }
  deriving ( Generic, Show )

emptyCache :: Cache
emptyCache = Cache Nothing SM.empty SM.empty SM.empty SM.empty LS.empty def

runCacheInMemory :: P.Member (P.Embed IO) r => P.Sem (CacheEff ': r) a -> P.Sem r a
runCacheInMemory m = do
  var <- P.embed $ newIORef emptyCache
  P.runAtomicStateIORef var $ P.reinterpret runCache' m

runCache' :: P.Member (P.AtomicState Cache) r => CacheEff m a -> P.Sem r a
runCache' act = P.atomicState' ((swap .) . runState $ runCache act)

runCache :: CacheEff m a -> State Cache a

runCache (SetBotUser u) = #user ?= u
runCache GetBotUser     = use #user

runCache (SetGuild g)   = #guilds %= SM.insert g
runCache (GetGuild gid) = use (#guilds . at gid)
runCache GetGuilds      = SM.elems <$> use #guilds
runCache (DelGuild gid) = #guilds %= sans gid

runCache (SetDM dm)  = #dms %= SM.insert dm
runCache (GetDM did) = use (#dms . at did)
runCache GetDMs      = SM.elems <$> use #dms
runCache (DelDM did) = #dms %= sans did

runCache (SetUser u)   = #users %= SM.insert u
runCache (GetUser uid) = use (#users . at uid)
runCache GetUsers      = SM.elems <$> use #users
runCache (DelUser uid) = #users %= sans uid

runCache (SetUnavailableGuild gid) = #unavailableGuilds %= LS.insert gid
runCache (IsUnavailableGuild gid)  = use (#unavailableGuilds . contains gid)
runCache GetUnavailableGuilds      = LS.toList <$> use #unavailableGuilds
runCache (DelUnavailableGuild gid) = #unavailableGuilds %= sans gid

runCache (SetMessage m)   = #messages %= addItem m
runCache (GetMessage mid) = use (#messages . at mid)
runCache GetMessages      = toList <$> use #messages
runCache (DelMessage mid) = #messages %= sans mid