{-# LANGUAGE BangPatterns, FlexibleContexts, OverloadedStrings, ScopedTypeVariables, TypeApplications, DataKinds, KindSignatures #-}
module Data.TinyLRU
(
TinyLRUCache(..)
, initTinyLRU
, access
, updateValue
, deleteKey
, resetTinyLRU
, allowRequestTinyLRU
, LRUList(..)
, LRUNode(..)
, isExpired
, addToFront
, removeNode
, moveToFront
, evictLRU
, removeNodeFromCache
, moveToFrontInCache
) where
import Control.Concurrent.STM
import StmContainers.Map (Map)
import qualified StmContainers.Map as Map
import Data.Text (Text)
import qualified Data.Text as T
import Data.ByteString (ByteString)
import qualified Data.ByteString.Lazy as BL
import Data.Aeson (FromJSON, ToJSON, encode, decodeStrict)
import System.Clock (TimeSpec(..))
import Data.Maybe (isNothing)
import Control.Monad (when, forM_, foldM)
import qualified ListT
data LRUNode s = LRUNode
{ forall s. LRUNode s -> Text
nodeKey :: !Text
, forall s. LRUNode s -> ByteString
nodeValue :: !ByteString
, forall s. LRUNode s -> Maybe TimeSpec
nodeExpiry :: !(Maybe TimeSpec)
, forall s. LRUNode s -> Maybe (TVar (LRUNode s))
nodePrev :: !(Maybe (TVar (LRUNode s)))
, forall s. LRUNode s -> Maybe (TVar (LRUNode s))
nodeNext :: !(Maybe (TVar (LRUNode s)))
}
data LRUList s = LRUList
{ forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead :: !(Maybe (TVar (LRUNode s)))
, forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail :: !(Maybe (TVar (LRUNode s)))
}
data TinyLRUCache s = TinyLRUCache
{ forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache :: !(Map Text (TVar (LRUNode s)))
, forall s. TinyLRUCache s -> TVar (LRUList s)
lruList :: !(TVar (LRUList s))
, forall s. TinyLRUCache s -> Int
lruCap :: !Int
}
initTinyLRU :: Int -> STM (TinyLRUCache s)
initTinyLRU :: forall s. Int -> STM (TinyLRUCache s)
initTinyLRU Int
cap = do
Map Text (TVar (LRUNode s))
cache <- STM (Map Text (TVar (LRUNode s)))
forall key value. STM (Map key value)
Map.new
TVar (LRUList s)
list <- LRUList s -> STM (TVar (LRUList s))
forall a. a -> STM (TVar a)
newTVar (LRUList s -> STM (TVar (LRUList s)))
-> LRUList s -> STM (TVar (LRUList s))
forall a b. (a -> b) -> a -> b
$ Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
forall s.
Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
LRUList Maybe (TVar (LRUNode s))
forall a. Maybe a
Nothing Maybe (TVar (LRUNode s))
forall a. Maybe a
Nothing
TinyLRUCache s -> STM (TinyLRUCache s)
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return (TinyLRUCache s -> STM (TinyLRUCache s))
-> TinyLRUCache s -> STM (TinyLRUCache s)
forall a b. (a -> b) -> a -> b
$ Map Text (TVar (LRUNode s))
-> TVar (LRUList s) -> Int -> TinyLRUCache s
forall s.
Map Text (TVar (LRUNode s))
-> TVar (LRUList s) -> Int -> TinyLRUCache s
TinyLRUCache Map Text (TVar (LRUNode s))
cache TVar (LRUList s)
list Int
cap
mkExpiry :: TimeSpec -> Int -> Maybe TimeSpec
mkExpiry :: TimeSpec -> Int -> Maybe TimeSpec
mkExpiry TimeSpec
now Int
ttl | Int
ttl Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = Maybe TimeSpec
forall a. Maybe a
Nothing
| Bool
otherwise = TimeSpec -> Maybe TimeSpec
forall a. a -> Maybe a
Just (TimeSpec -> Maybe TimeSpec) -> TimeSpec -> Maybe TimeSpec
forall a b. (a -> b) -> a -> b
$ TimeSpec -> Int -> TimeSpec
addTTL TimeSpec
now Int
ttl
isExpired :: TimeSpec -> LRUNode s -> Bool
isExpired :: forall s. TimeSpec -> LRUNode s -> Bool
isExpired TimeSpec
now LRUNode s
node =
case LRUNode s -> Maybe TimeSpec
forall s. LRUNode s -> Maybe TimeSpec
nodeExpiry LRUNode s
node of
Maybe TimeSpec
Nothing -> Bool
False
Just TimeSpec
expTime -> TimeSpec
now TimeSpec -> TimeSpec -> Bool
forall a. Ord a => a -> a -> Bool
>= TimeSpec
expTime
removeNode :: TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode :: forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode TVar (LRUList s)
listTVar TVar (LRUNode s)
nodeTVar = do
LRUNode s
node <- TVar (LRUNode s) -> STM (LRUNode s)
forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
let mPrev :: Maybe (TVar (LRUNode s))
mPrev = LRUNode s -> Maybe (TVar (LRUNode s))
forall s. LRUNode s -> Maybe (TVar (LRUNode s))
nodePrev LRUNode s
node
mNext :: Maybe (TVar (LRUNode s))
mNext = LRUNode s -> Maybe (TVar (LRUNode s))
forall s. LRUNode s -> Maybe (TVar (LRUNode s))
nodeNext LRUNode s
node
Maybe (TVar (LRUNode s)) -> (TVar (LRUNode s) -> STM ()) -> STM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar (LRUNode s))
mPrev ((TVar (LRUNode s) -> STM ()) -> STM ())
-> (TVar (LRUNode s) -> STM ()) -> STM ()
forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
pRef -> TVar (LRUNode s) -> (LRUNode s -> LRUNode s) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (LRUNode s)
pRef (\LRUNode s
p -> LRUNode s
p { nodeNext = mNext })
Maybe (TVar (LRUNode s)) -> (TVar (LRUNode s) -> STM ()) -> STM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar (LRUNode s))
mNext ((TVar (LRUNode s) -> STM ()) -> STM ())
-> (TVar (LRUNode s) -> STM ()) -> STM ()
forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
nRef -> TVar (LRUNode s) -> (LRUNode s -> LRUNode s) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (LRUNode s)
nRef (\LRUNode s
n -> LRUNode s
n { nodePrev = mPrev })
TVar (LRUList s) -> (LRUList s -> LRUList s) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (LRUList s)
listTVar ((LRUList s -> LRUList s) -> STM ())
-> (LRUList s -> LRUList s) -> STM ()
forall a b. (a -> b) -> a -> b
$ \LRUList s
list ->
let newHead :: Maybe (TVar (LRUNode s))
newHead = if LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> Bool
forall a. Eq a => a -> a -> Bool
== TVar (LRUNode s) -> Maybe (TVar (LRUNode s))
forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar then Maybe (TVar (LRUNode s))
mNext else LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list
newTail :: Maybe (TVar (LRUNode s))
newTail = if LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> Bool
forall a. Eq a => a -> a -> Bool
== TVar (LRUNode s) -> Maybe (TVar (LRUNode s))
forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar then Maybe (TVar (LRUNode s))
mPrev else LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list
in LRUList s
list { lruHead = newHead, lruTail = newTail }
addToFront :: TimeSpec -> Int -> TinyLRUCache s -> Text -> ByteString -> STM (TVar (LRUNode s))
addToFront :: forall s.
TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
addToFront TimeSpec
now Int
ttl TinyLRUCache s
cache Text
key ByteString
value = do
let expiry :: Maybe TimeSpec
expiry = TimeSpec -> Int -> Maybe TimeSpec
mkExpiry TimeSpec
now Int
ttl
LRUList s
list <- TVar (LRUList s) -> STM (LRUList s)
forall a. TVar a -> STM a
readTVar (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache)
TVar (LRUNode s)
nodeTVar <- LRUNode s -> STM (TVar (LRUNode s))
forall a. a -> STM (TVar a)
newTVar (LRUNode s -> STM (TVar (LRUNode s)))
-> LRUNode s -> STM (TVar (LRUNode s))
forall a b. (a -> b) -> a -> b
$ Text
-> ByteString
-> Maybe TimeSpec
-> Maybe (TVar (LRUNode s))
-> Maybe (TVar (LRUNode s))
-> LRUNode s
forall s.
Text
-> ByteString
-> Maybe TimeSpec
-> Maybe (TVar (LRUNode s))
-> Maybe (TVar (LRUNode s))
-> LRUNode s
LRUNode Text
key ByteString
value Maybe TimeSpec
expiry Maybe (TVar (LRUNode s))
forall a. Maybe a
Nothing (LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list)
Maybe (TVar (LRUNode s)) -> (TVar (LRUNode s) -> STM ()) -> STM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list) ((TVar (LRUNode s) -> STM ()) -> STM ())
-> (TVar (LRUNode s) -> STM ()) -> STM ()
forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
oldHeadTVar -> do
LRUNode s
oldHead <- TVar (LRUNode s) -> STM (LRUNode s)
forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
oldHeadTVar
TVar (LRUNode s) -> LRUNode s -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUNode s)
oldHeadTVar LRUNode s
oldHead { nodePrev = Just nodeTVar }
let newTail :: Maybe (TVar (LRUNode s))
newTail = if Maybe (TVar (LRUNode s)) -> Bool
forall a. Maybe a -> Bool
isNothing (LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list) then TVar (LRUNode s) -> Maybe (TVar (LRUNode s))
forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar else LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list
TVar (LRUList s) -> LRUList s -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) (Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
forall s.
Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
LRUList (TVar (LRUNode s) -> Maybe (TVar (LRUNode s))
forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar) Maybe (TVar (LRUNode s))
newTail)
TVar (LRUNode s) -> STM (TVar (LRUNode s))
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return TVar (LRUNode s)
nodeTVar
moveToFront :: TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront :: forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront TVar (LRUList s)
listTVar TVar (LRUNode s)
nodeTVar = do
LRUList s
list <- TVar (LRUList s) -> STM (LRUList s)
forall a. TVar a -> STM a
readTVar TVar (LRUList s)
listTVar
Bool -> STM () -> STM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> Bool
forall a. Eq a => a -> a -> Bool
/= TVar (LRUNode s) -> Maybe (TVar (LRUNode s))
forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar) (STM () -> STM ()) -> STM () -> STM ()
forall a b. (a -> b) -> a -> b
$ do
TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode TVar (LRUList s)
listTVar TVar (LRUNode s)
nodeTVar
LRUNode s
node <- TVar (LRUNode s) -> STM (LRUNode s)
forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
LRUList s
list' <- TVar (LRUList s) -> STM (LRUList s)
forall a. TVar a -> STM a
readTVar TVar (LRUList s)
listTVar
let mOldHead :: Maybe (TVar (LRUNode s))
mOldHead = LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list'
TVar (LRUNode s) -> LRUNode s -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUNode s)
nodeTVar LRUNode s
node { nodePrev = Nothing, nodeNext = mOldHead }
Maybe (TVar (LRUNode s)) -> (TVar (LRUNode s) -> STM ()) -> STM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar (LRUNode s))
mOldHead ((TVar (LRUNode s) -> STM ()) -> STM ())
-> (TVar (LRUNode s) -> STM ()) -> STM ()
forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
oldHeadTVar ->
TVar (LRUNode s) -> (LRUNode s -> LRUNode s) -> STM ()
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (LRUNode s)
oldHeadTVar (\LRUNode s
h -> LRUNode s
h { nodePrev = Just nodeTVar })
let newTail :: Maybe (TVar (LRUNode s))
newTail = if Maybe (TVar (LRUNode s)) -> Bool
forall a. Maybe a -> Bool
isNothing (LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list') then TVar (LRUNode s) -> Maybe (TVar (LRUNode s))
forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar else LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list'
TVar (LRUList s) -> LRUList s -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUList s)
listTVar (Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
forall s.
Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
LRUList (TVar (LRUNode s) -> Maybe (TVar (LRUNode s))
forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar) Maybe (TVar (LRUNode s))
newTail)
evictLRU :: TinyLRUCache s -> STM ()
evictLRU :: forall s. TinyLRUCache s -> STM ()
evictLRU TinyLRUCache s
cache = do
LRUList s
list <- TVar (LRUList s) -> STM (LRUList s)
forall a. TVar a -> STM a
readTVar (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache)
Maybe (TVar (LRUNode s)) -> (TVar (LRUNode s) -> STM ()) -> STM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (LRUList s -> Maybe (TVar (LRUNode s))
forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list) ((TVar (LRUNode s) -> STM ()) -> STM ())
-> (TVar (LRUNode s) -> STM ()) -> STM ()
forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
tailTVar -> do
LRUNode s
node <- TVar (LRUNode s) -> STM (LRUNode s)
forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
tailTVar
Text -> Map Text (TVar (LRUNode s)) -> STM ()
forall key value. Hashable key => key -> Map key value -> STM ()
Map.delete (LRUNode s -> Text
forall s. LRUNode s -> Text
nodeKey LRUNode s
node) (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
tailTVar
addTTL :: TimeSpec -> Int -> TimeSpec
addTTL :: TimeSpec -> Int -> TimeSpec
addTTL (TimeSpec Int64
s Int64
ns) Int
ttl = Int64 -> Int64 -> TimeSpec
TimeSpec (Int64
s Int64 -> Int64 -> Int64
forall a. Num a => a -> a -> a
+ Int -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 Int
ttl)) Int64
ns
deleteKey :: Text -> TinyLRUCache s -> STM ()
deleteKey :: forall s. Text -> TinyLRUCache s -> STM ()
deleteKey Text
key TinyLRUCache s
cache = do
Maybe (TVar (LRUNode s))
mNodeTVar <- Text
-> Map Text (TVar (LRUNode s)) -> STM (Maybe (TVar (LRUNode s)))
forall key value.
Hashable key =>
key -> Map key value -> STM (Maybe value)
Map.lookup Text
key (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
Maybe (TVar (LRUNode s)) -> (TVar (LRUNode s) -> STM ()) -> STM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar (LRUNode s))
mNodeTVar ((TVar (LRUNode s) -> STM ()) -> STM ())
-> (TVar (LRUNode s) -> STM ()) -> STM ()
forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
nodeTVar -> do
Text -> Map Text (TVar (LRUNode s)) -> STM ()
forall key value. Hashable key => key -> Map key value -> STM ()
Map.delete Text
key (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
cleanupExpired :: TimeSpec -> TinyLRUCache s -> STM ()
cleanupExpired :: forall s. TimeSpec -> TinyLRUCache s -> STM ()
cleanupExpired TimeSpec
now TinyLRUCache s
cache = do
[(Text, TVar (LRUNode s))]
pairs <- ListT STM (Text, TVar (LRUNode s))
-> STM [(Text, TVar (LRUNode s))]
forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
ListT.toList (ListT STM (Text, TVar (LRUNode s))
-> STM [(Text, TVar (LRUNode s))])
-> ListT STM (Text, TVar (LRUNode s))
-> STM [(Text, TVar (LRUNode s))]
forall a b. (a -> b) -> a -> b
$ Map Text (TVar (LRUNode s)) -> ListT STM (Text, TVar (LRUNode s))
forall key value. Map key value -> ListT STM (key, value)
Map.listT (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
[Text]
expired <- ([Text] -> (Text, TVar (LRUNode s)) -> STM [Text])
-> [Text] -> [(Text, TVar (LRUNode s))] -> STM [Text]
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (\[Text]
acc (Text
k, TVar (LRUNode s)
nodeRef) -> do
LRUNode s
node <- TVar (LRUNode s) -> STM (LRUNode s)
forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeRef
if TimeSpec -> LRUNode s -> Bool
forall s. TimeSpec -> LRUNode s -> Bool
isExpired TimeSpec
now LRUNode s
node then [Text] -> STM [Text]
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
kText -> [Text] -> [Text]
forall a. a -> [a] -> [a]
:[Text]
acc) else [Text] -> STM [Text]
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return [Text]
acc
) [] [(Text, TVar (LRUNode s))]
pairs
[Text] -> (Text -> STM ()) -> STM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Text]
expired ((Text -> STM ()) -> STM ()) -> (Text -> STM ()) -> STM ()
forall a b. (a -> b) -> a -> b
$ \Text
k -> Text -> TinyLRUCache s -> STM ()
forall s. Text -> TinyLRUCache s -> STM ()
deleteKey Text
k TinyLRUCache s
cache
access :: forall a s. (FromJSON a, ToJSON a) => TimeSpec -> Text -> a -> Int -> TinyLRUCache s -> STM (Maybe a)
access :: forall a s.
(FromJSON a, ToJSON a) =>
TimeSpec -> Text -> a -> Int -> TinyLRUCache s -> STM (Maybe a)
access TimeSpec
now Text
key a
val Int
ttl TinyLRUCache s
cache
| Text -> Bool
T.null Text
key Bool -> Bool -> Bool
|| Text -> Int
T.length Text
key Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
256 = Maybe a -> STM (Maybe a)
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
| Bool
otherwise = do
TimeSpec -> TinyLRUCache s -> STM ()
forall s. TimeSpec -> TinyLRUCache s -> STM ()
cleanupExpired TimeSpec
now TinyLRUCache s
cache
Maybe (TVar (LRUNode s))
mNodeTVar <- Text
-> Map Text (TVar (LRUNode s)) -> STM (Maybe (TVar (LRUNode s)))
forall key value.
Hashable key =>
key -> Map key value -> STM (Maybe value)
Map.lookup Text
key (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
case Maybe (TVar (LRUNode s))
mNodeTVar of
Just TVar (LRUNode s)
nodeTVar -> do
LRUNode s
node <- TVar (LRUNode s) -> STM (LRUNode s)
forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
if TimeSpec -> LRUNode s -> Bool
forall s. TimeSpec -> LRUNode s -> Bool
isExpired TimeSpec
now LRUNode s
node then do
Text -> TinyLRUCache s -> STM ()
forall s. Text -> TinyLRUCache s -> STM ()
deleteKey Text
key TinyLRUCache s
cache
STM (Maybe a)
insertNew
else do
TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
case ByteString -> Maybe a
forall a. FromJSON a => ByteString -> Maybe a
decodeStrict (LRUNode s -> ByteString
forall s. LRUNode s -> ByteString
nodeValue LRUNode s
node) :: Maybe a of
Just a
existingVal -> Maybe a -> STM (Maybe a)
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Maybe a
forall a. a -> Maybe a
Just a
existingVal)
Maybe a
Nothing -> do
Text -> TinyLRUCache s -> STM ()
forall s. Text -> TinyLRUCache s -> STM ()
deleteKey Text
key TinyLRUCache s
cache
STM (Maybe a)
insertNew
Maybe (TVar (LRUNode s))
Nothing -> STM (Maybe a)
insertNew
where
insertNew :: STM (Maybe a)
insertNew = do
Int
sz <- Map Text (TVar (LRUNode s)) -> STM Int
forall key value. Map key value -> STM Int
Map.size (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
Bool -> STM () -> STM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
sz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= TinyLRUCache s -> Int
forall s. TinyLRUCache s -> Int
lruCap TinyLRUCache s
cache) (STM () -> STM ()) -> STM () -> STM ()
forall a b. (a -> b) -> a -> b
$ TinyLRUCache s -> STM ()
forall s. TinyLRUCache s -> STM ()
evictLRU TinyLRUCache s
cache
TVar (LRUNode s)
nodeTVar <- TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
forall s.
TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
addToFront TimeSpec
now Int
ttl TinyLRUCache s
cache Text
key (LazyByteString -> ByteString
BL.toStrict (a -> LazyByteString
forall a. ToJSON a => a -> LazyByteString
encode a
val))
TVar (LRUNode s) -> Text -> Map Text (TVar (LRUNode s)) -> STM ()
forall key value.
Hashable key =>
value -> key -> Map key value -> STM ()
Map.insert TVar (LRUNode s)
nodeTVar Text
key (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
Maybe a -> STM (Maybe a)
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Maybe a
forall a. a -> Maybe a
Just a
val)
updateValue :: forall a s. (FromJSON a, ToJSON a) => TimeSpec -> Text -> a -> Int -> TinyLRUCache s -> STM (Maybe a)
updateValue :: forall a s.
(FromJSON a, ToJSON a) =>
TimeSpec -> Text -> a -> Int -> TinyLRUCache s -> STM (Maybe a)
updateValue TimeSpec
now Text
key a
val Int
ttl TinyLRUCache s
cache
| Text -> Bool
T.null Text
key Bool -> Bool -> Bool
|| Text -> Int
T.length Text
key Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
256 = Maybe a -> STM (Maybe a)
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
| Bool
otherwise = do
TimeSpec -> TinyLRUCache s -> STM ()
forall s. TimeSpec -> TinyLRUCache s -> STM ()
cleanupExpired TimeSpec
now TinyLRUCache s
cache
Maybe (TVar (LRUNode s))
mNodeTVar <- Text
-> Map Text (TVar (LRUNode s)) -> STM (Maybe (TVar (LRUNode s)))
forall key value.
Hashable key =>
key -> Map key value -> STM (Maybe value)
Map.lookup Text
key (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
case Maybe (TVar (LRUNode s))
mNodeTVar of
Just TVar (LRUNode s)
nodeTVar -> do
LRUNode s
node <- TVar (LRUNode s) -> STM (LRUNode s)
forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
let newExpiry :: Maybe TimeSpec
newExpiry = TimeSpec -> Int -> Maybe TimeSpec
mkExpiry TimeSpec
now Int
ttl
TVar (LRUNode s) -> LRUNode s -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUNode s)
nodeTVar LRUNode s
node {
nodeValue = BL.toStrict (encode val),
nodeExpiry = newExpiry
}
TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
Maybe a -> STM (Maybe a)
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Maybe a
forall a. a -> Maybe a
Just a
val)
Maybe (TVar (LRUNode s))
Nothing -> do
Int
sz <- Map Text (TVar (LRUNode s)) -> STM Int
forall key value. Map key value -> STM Int
Map.size (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
Bool -> STM () -> STM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
sz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= TinyLRUCache s -> Int
forall s. TinyLRUCache s -> Int
lruCap TinyLRUCache s
cache) (STM () -> STM ()) -> STM () -> STM ()
forall a b. (a -> b) -> a -> b
$ TinyLRUCache s -> STM ()
forall s. TinyLRUCache s -> STM ()
evictLRU TinyLRUCache s
cache
TVar (LRUNode s)
nodeTVar <- TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
forall s.
TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
addToFront TimeSpec
now Int
ttl TinyLRUCache s
cache Text
key (LazyByteString -> ByteString
BL.toStrict (a -> LazyByteString
forall a. ToJSON a => a -> LazyByteString
encode a
val))
TVar (LRUNode s) -> Text -> Map Text (TVar (LRUNode s)) -> STM ()
forall key value.
Hashable key =>
value -> key -> Map key value -> STM ()
Map.insert TVar (LRUNode s)
nodeTVar Text
key (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
Maybe a -> STM (Maybe a)
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> Maybe a
forall a. a -> Maybe a
Just a
val)
resetTinyLRU :: TinyLRUCache s -> STM ()
resetTinyLRU :: forall s. TinyLRUCache s -> STM ()
resetTinyLRU TinyLRUCache s
cache = do
Map Text (TVar (LRUNode s)) -> STM ()
forall key value. Map key value -> STM ()
Map.reset (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
TVar (LRUList s) -> LRUList s -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) (LRUList s -> STM ()) -> LRUList s -> STM ()
forall a b. (a -> b) -> a -> b
$ Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
forall s.
Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
LRUList Maybe (TVar (LRUNode s))
forall a. Maybe a
Nothing Maybe (TVar (LRUNode s))
forall a. Maybe a
Nothing
allowRequestTinyLRU :: TimeSpec -> TinyLRUCache s -> Text -> Int -> Int -> STM Bool
allowRequestTinyLRU :: forall s.
TimeSpec -> TinyLRUCache s -> Text -> Int -> Int -> STM Bool
allowRequestTinyLRU TimeSpec
now TinyLRUCache s
cache Text
key Int
limit Int
period
| Text -> Bool
T.null Text
key = Bool -> STM Bool
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
| Bool
otherwise = do
TimeSpec -> TinyLRUCache s -> STM ()
forall s. TimeSpec -> TinyLRUCache s -> STM ()
cleanupExpired TimeSpec
now TinyLRUCache s
cache
Maybe (TVar (LRUNode s))
mNodeTVar <- Text
-> Map Text (TVar (LRUNode s)) -> STM (Maybe (TVar (LRUNode s)))
forall key value.
Hashable key =>
key -> Map key value -> STM (Maybe value)
Map.lookup Text
key (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
case Maybe (TVar (LRUNode s))
mNodeTVar of
Just TVar (LRUNode s)
nodeTVar -> do
LRUNode s
node <- TVar (LRUNode s) -> STM (LRUNode s)
forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
if TimeSpec -> LRUNode s -> Bool
forall s. TimeSpec -> LRUNode s -> Bool
isExpired TimeSpec
now LRUNode s
node then do
Text -> TinyLRUCache s -> STM ()
forall s. Text -> TinyLRUCache s -> STM ()
deleteKey Text
key TinyLRUCache s
cache
STM Bool
insertNew
else do
case ByteString -> Maybe Int
forall a. FromJSON a => ByteString -> Maybe a
decodeStrict (LRUNode s -> ByteString
forall s. LRUNode s -> ByteString
nodeValue LRUNode s
node) :: Maybe Int of
Just Int
n
| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
limit -> do
let newExpiry :: Maybe TimeSpec
newExpiry = TimeSpec -> Int -> Maybe TimeSpec
mkExpiry TimeSpec
now Int
period
TVar (LRUNode s) -> LRUNode s -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUNode s)
nodeTVar LRUNode s
node {
nodeValue = BL.toStrict (encode (n+1)),
nodeExpiry = newExpiry
}
TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
Bool -> STM Bool
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
| Bool
otherwise -> do
TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
Bool -> STM Bool
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
Maybe Int
_ -> do
Text -> TinyLRUCache s -> STM ()
forall s. Text -> TinyLRUCache s -> STM ()
deleteKey Text
key TinyLRUCache s
cache
STM Bool
insertNew
Maybe (TVar (LRUNode s))
Nothing -> STM Bool
insertNew
where
insertNew :: STM Bool
insertNew = do
Int
sz <- Map Text (TVar (LRUNode s)) -> STM Int
forall key value. Map key value -> STM Int
Map.size (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
Bool -> STM () -> STM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
sz Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= TinyLRUCache s -> Int
forall s. TinyLRUCache s -> Int
lruCap TinyLRUCache s
cache) (STM () -> STM ()) -> STM () -> STM ()
forall a b. (a -> b) -> a -> b
$ TinyLRUCache s -> STM ()
forall s. TinyLRUCache s -> STM ()
evictLRU TinyLRUCache s
cache
TVar (LRUNode s)
nodeTVar <- TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
forall s.
TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
addToFront TimeSpec
now Int
period TinyLRUCache s
cache Text
key (LazyByteString -> ByteString
BL.toStrict (Int -> LazyByteString
forall a. ToJSON a => a -> LazyByteString
encode (Int
1 :: Int)))
TVar (LRUNode s) -> Text -> Map Text (TVar (LRUNode s)) -> STM ()
forall key value.
Hashable key =>
value -> key -> Map key value -> STM ()
Map.insert TVar (LRUNode s)
nodeTVar Text
key (TinyLRUCache s -> Map Text (TVar (LRUNode s))
forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
Bool -> STM Bool
forall a. a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
removeNodeFromCache :: TinyLRUCache s -> TVar (LRUNode s) -> STM ()
removeNodeFromCache :: forall s. TinyLRUCache s -> TVar (LRUNode s) -> STM ()
removeNodeFromCache TinyLRUCache s
cache = TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache)
moveToFrontInCache :: TinyLRUCache s -> TVar (LRUNode s) -> STM ()
moveToFrontInCache :: forall s. TinyLRUCache s -> TVar (LRUNode s) -> STM ()
moveToFrontInCache TinyLRUCache s
cache = TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (TinyLRUCache s -> TVar (LRUList s)
forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache)