Repository navigation
Expand file tree
/
Copy pathCache.hs
More file actions
84 lines (74 loc) · 2.35 KB
/
Copy pathCache.hs
File metadata and controls
84 lines (74 loc) · 2.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
{-# OPTIONS_GHC -fplugin=Polysemy.Plugin #-}
module Cache where
import Calamity hiding (Embed, Member)
import Control.Monad.IO.Class
import Data.Default
import Data.List.NonEmpty (NonEmpty)
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as M
import Data.Set (Set)
import Data.Set qualified as S
import Data.Time
import Polysemy
import Polysemy.AtomicState
import Polysemy.Reader
import Config
import Types
data ActiveMessage = ActiveMessage
{ id :: !(Snowflake Message)
, updated :: !UTCTime
, channel :: !(Snowflake Channel)
, commands :: !(Maybe (NonEmpty Command))
, response :: !(Maybe (Snowflake Message))
}
deriving Show
data EvalState = EvalState
{ messageById :: !(Map (Snowflake Message) ActiveMessage)
, messageByAge :: !(Set (UTCTime, Snowflake Message))
}
instance Default EvalState where
def = EvalState
{ messageById = M.empty
, messageByAge = S.empty
}
pruneMessages
:: Members '[Embed IO, Reader EvalConfig, AtomicState EvalState] r => Sem r ()
pruneMessages = do
config <- ask
now <- liftIO getCurrentTime
atomicModify' \state -> let
(pruned, messageByAge) = S.spanAntitone
(\(t, _) -> now `diffUTCTime` t > secondsToNominalDiffTime
(fromIntegral config.forgetAfterSeconds))
state.messageByAge
messageById = state.messageById `M.withoutKeys` S.map snd pruned
in state
{ messageByAge
, messageById
}
lookupMessage
:: Member (AtomicState EvalState) r
=> Snowflake Message -> Sem r (Maybe ActiveMessage)
lookupMessage mId = M.lookup mId . (.messageById) <$> atomicGet
upsertMessage
:: Member (AtomicState EvalState) r => ActiveMessage -> Sem r ()
upsertMessage am = atomicModify' \state ->
let
(mOldAm, messageById) = M.insertLookupWithKey
(\_ new _old -> new) am.id am state.messageById
messageByAge = S.insert (am.updated, am.id) case mOldAm of
Nothing -> state.messageByAge
Just oldAm -> S.delete (oldAm.updated, oldAm.id) state.messageByAge
in state
{ messageById
, messageByAge
}
deleteMessage
:: Member (AtomicState EvalState) r => Snowflake Message -> Sem r ()
deleteMessage mId = atomicModify' \state ->
case M.lookup mId state.messageById of
Just am -> state
{ messageById = M.delete mId state.messageById
, messageByAge = S.delete (am.updated, am.id) state.messageByAge
}
Nothing -> state