{-# 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 <- forall key value. STM (Map key value)
Map.new
TVar (LRUList s)
list <- forall a. a -> STM (TVar a)
newTVar forall a b. (a -> b) -> a -> b
$ forall s.
Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
LRUList forall a. Maybe a
Nothing forall a. Maybe a
Nothing
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ 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 forall a. Ord a => a -> a -> Bool
<= Int
0 = forall a. Maybe a
Nothing
| Bool
otherwise = forall a. a -> Maybe a
Just 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 forall s. LRUNode s -> Maybe TimeSpec
nodeExpiry LRUNode s
node of
Maybe TimeSpec
Nothing -> Bool
False
Just TimeSpec
expTime -> TimeSpec
now 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 <- forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
let mPrev :: Maybe (TVar (LRUNode s))
mPrev = forall s. LRUNode s -> Maybe (TVar (LRUNode s))
nodePrev LRUNode s
node
mNext :: Maybe (TVar (LRUNode s))
mNext = forall s. LRUNode s -> Maybe (TVar (LRUNode s))
nodeNext LRUNode s
node
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar (LRUNode s))
mPrev forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
pRef -> forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (LRUNode s)
pRef (\LRUNode s
p -> LRUNode s
p { nodeNext :: Maybe (TVar (LRUNode s))
nodeNext = Maybe (TVar (LRUNode s))
mNext })
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar (LRUNode s))
mNext forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
nRef -> forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (LRUNode s)
nRef (\LRUNode s
n -> LRUNode s
n { nodePrev :: Maybe (TVar (LRUNode s))
nodePrev = Maybe (TVar (LRUNode s))
mPrev })
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (LRUList s)
listTVar forall a b. (a -> b) -> a -> b
$ \LRUList s
list ->
let newHead :: Maybe (TVar (LRUNode s))
newHead = if forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar then Maybe (TVar (LRUNode s))
mNext else forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list
newTail :: Maybe (TVar (LRUNode s))
newTail = if forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list forall a. Eq a => a -> a -> Bool
== forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar then Maybe (TVar (LRUNode s))
mPrev else forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list
in LRUList s
list { lruHead :: Maybe (TVar (LRUNode s))
lruHead = Maybe (TVar (LRUNode s))
newHead, lruTail :: Maybe (TVar (LRUNode s))
lruTail = Maybe (TVar (LRUNode s))
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 <- forall a. TVar a -> STM a
readTVar (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache)
TVar (LRUNode s)
nodeTVar <- forall a. a -> STM (TVar a)
newTVar forall a b. (a -> b) -> a -> b
$ forall s.
Text
-> ByteString
-> Maybe TimeSpec
-> Maybe (TVar (LRUNode s))
-> Maybe (TVar (LRUNode s))
-> LRUNode s
LRUNode Text
key ByteString
value Maybe TimeSpec
expiry forall a. Maybe a
Nothing (forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list)
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list) forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
oldHeadTVar -> do
LRUNode s
oldHead <- forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
oldHeadTVar
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUNode s)
oldHeadTVar LRUNode s
oldHead { nodePrev :: Maybe (TVar (LRUNode s))
nodePrev = forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar }
let newTail :: Maybe (TVar (LRUNode s))
newTail = if forall a. Maybe a -> Bool
isNothing (forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list) then forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar else forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list
forall a. TVar a -> a -> STM ()
writeTVar (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) (forall s.
Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
LRUList (forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar) Maybe (TVar (LRUNode s))
newTail)
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 <- forall a. TVar a -> STM a
readTVar TVar (LRUList s)
listTVar
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list forall a. Eq a => a -> a -> Bool
/= forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar) forall a b. (a -> b) -> a -> b
$ do
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode TVar (LRUList s)
listTVar TVar (LRUNode s)
nodeTVar
LRUNode s
node <- forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
LRUList s
list' <- forall a. TVar a -> STM a
readTVar TVar (LRUList s)
listTVar
let mOldHead :: Maybe (TVar (LRUNode s))
mOldHead = forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruHead LRUList s
list'
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUNode s)
nodeTVar LRUNode s
node { nodePrev :: Maybe (TVar (LRUNode s))
nodePrev = forall a. Maybe a
Nothing, nodeNext :: Maybe (TVar (LRUNode s))
nodeNext = Maybe (TVar (LRUNode s))
mOldHead }
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar (LRUNode s))
mOldHead forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
oldHeadTVar ->
forall a. TVar a -> (a -> a) -> STM ()
modifyTVar' TVar (LRUNode s)
oldHeadTVar (\LRUNode s
h -> LRUNode s
h { nodePrev :: Maybe (TVar (LRUNode s))
nodePrev = forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar })
let newTail :: Maybe (TVar (LRUNode s))
newTail = if forall a. Maybe a -> Bool
isNothing (forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list') then forall a. a -> Maybe a
Just TVar (LRUNode s)
nodeTVar else forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list'
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUList s)
listTVar (forall s.
Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
LRUList (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 <- forall a. TVar a -> STM a
readTVar (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache)
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (forall s. LRUList s -> Maybe (TVar (LRUNode s))
lruTail LRUList s
list) forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
tailTVar -> do
LRUNode s
node <- forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
tailTVar
forall key value. Hashable key => key -> Map key value -> STM ()
Map.delete (forall s. LRUNode s -> Text
nodeKey LRUNode s
node) (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode (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 forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral (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 <- forall key value.
Hashable key =>
key -> Map key value -> STM (Maybe value)
Map.lookup Text
key (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe (TVar (LRUNode s))
mNodeTVar forall a b. (a -> b) -> a -> b
$ \TVar (LRUNode s)
nodeTVar -> do
forall key value. Hashable key => key -> Map key value -> STM ()
Map.delete Text
key (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode (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 <- forall (m :: * -> *) a. Monad m => ListT m a -> m [a]
ListT.toList forall a b. (a -> b) -> a -> b
$ forall key value. Map key value -> ListT STM (key, value)
Map.listT (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
[Text]
expired <- 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 <- forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeRef
if forall s. TimeSpec -> LRUNode s -> Bool
isExpired TimeSpec
now LRUNode s
node then forall (m :: * -> *) a. Monad m => a -> m a
return (Text
kforall a. a -> [a] -> [a]
:[Text]
acc) else forall (m :: * -> *) a. Monad m => a -> m a
return [Text]
acc
) [] [(Text, TVar (LRUNode s))]
pairs
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Text]
expired forall a b. (a -> b) -> a -> b
$ \Text
k -> 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 forall a. Ord a => a -> a -> Bool
> Int
256 = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
| Bool
otherwise = do
forall s. TimeSpec -> TinyLRUCache s -> STM ()
cleanupExpired TimeSpec
now TinyLRUCache s
cache
Maybe (TVar (LRUNode s))
mNodeTVar <- forall key value.
Hashable key =>
key -> Map key value -> STM (Maybe value)
Map.lookup Text
key (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 <- forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
if forall s. TimeSpec -> LRUNode s -> Bool
isExpired TimeSpec
now LRUNode s
node then do
forall s. Text -> TinyLRUCache s -> STM ()
deleteKey Text
key TinyLRUCache s
cache
STM (Maybe a)
insertNew
else do
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
case forall a. FromJSON a => ByteString -> Maybe a
decodeStrict (forall s. LRUNode s -> ByteString
nodeValue LRUNode s
node) :: Maybe a of
Just a
existingVal -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just a
existingVal)
Maybe a
Nothing -> do
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 <- forall key value. Map key value -> STM Int
Map.size (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
sz forall a. Ord a => a -> a -> Bool
>= forall s. TinyLRUCache s -> Int
lruCap TinyLRUCache s
cache) forall a b. (a -> b) -> a -> b
$ forall s. TinyLRUCache s -> STM ()
evictLRU TinyLRUCache s
cache
TVar (LRUNode s)
nodeTVar <- forall s.
TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
addToFront TimeSpec
now Int
ttl TinyLRUCache s
cache Text
key (ByteString -> ByteString
BL.toStrict (forall a. ToJSON a => a -> ByteString
encode a
val))
forall key value.
Hashable key =>
value -> key -> Map key value -> STM ()
Map.insert TVar (LRUNode s)
nodeTVar Text
key (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall (m :: * -> *) a. Monad m => a -> m a
return (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 forall a. Ord a => a -> a -> Bool
> Int
256 = forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
| Bool
otherwise = do
forall s. TimeSpec -> TinyLRUCache s -> STM ()
cleanupExpired TimeSpec
now TinyLRUCache s
cache
Maybe (TVar (LRUNode s))
mNodeTVar <- forall key value.
Hashable key =>
key -> Map key value -> STM (Maybe value)
Map.lookup Text
key (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 <- 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
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUNode s)
nodeTVar LRUNode s
node {
nodeValue :: ByteString
nodeValue = ByteString -> ByteString
BL.toStrict (forall a. ToJSON a => a -> ByteString
encode a
val),
nodeExpiry :: Maybe TimeSpec
nodeExpiry = Maybe TimeSpec
newExpiry
}
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just a
val)
Maybe (TVar (LRUNode s))
Nothing -> do
Int
sz <- forall key value. Map key value -> STM Int
Map.size (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
sz forall a. Ord a => a -> a -> Bool
>= forall s. TinyLRUCache s -> Int
lruCap TinyLRUCache s
cache) forall a b. (a -> b) -> a -> b
$ forall s. TinyLRUCache s -> STM ()
evictLRU TinyLRUCache s
cache
TVar (LRUNode s)
nodeTVar <- forall s.
TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
addToFront TimeSpec
now Int
ttl TinyLRUCache s
cache Text
key (ByteString -> ByteString
BL.toStrict (forall a. ToJSON a => a -> ByteString
encode a
val))
forall key value.
Hashable key =>
value -> key -> Map key value -> STM ()
Map.insert TVar (LRUNode s)
nodeTVar Text
key (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just a
val)
resetTinyLRU :: TinyLRUCache s -> STM ()
resetTinyLRU :: forall s. TinyLRUCache s -> STM ()
resetTinyLRU TinyLRUCache s
cache = do
forall key value. Map key value -> STM ()
Map.reset (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall a. TVar a -> a -> STM ()
writeTVar (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) forall a b. (a -> b) -> a -> b
$ forall s.
Maybe (TVar (LRUNode s)) -> Maybe (TVar (LRUNode s)) -> LRUList s
LRUList forall a. Maybe a
Nothing 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 = forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
| Bool
otherwise = do
forall s. TimeSpec -> TinyLRUCache s -> STM ()
cleanupExpired TimeSpec
now TinyLRUCache s
cache
Maybe (TVar (LRUNode s))
mNodeTVar <- forall key value.
Hashable key =>
key -> Map key value -> STM (Maybe value)
Map.lookup Text
key (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 <- forall a. TVar a -> STM a
readTVar TVar (LRUNode s)
nodeTVar
if forall s. TimeSpec -> LRUNode s -> Bool
isExpired TimeSpec
now LRUNode s
node then do
forall s. Text -> TinyLRUCache s -> STM ()
deleteKey Text
key TinyLRUCache s
cache
STM Bool
insertNew
else do
case forall a. FromJSON a => ByteString -> Maybe a
decodeStrict (forall s. LRUNode s -> ByteString
nodeValue LRUNode s
node) :: Maybe Int of
Just Int
n
| Int
n forall a. Ord a => a -> a -> Bool
< Int
limit -> do
let newExpiry :: Maybe TimeSpec
newExpiry = TimeSpec -> Int -> Maybe TimeSpec
mkExpiry TimeSpec
now Int
period
forall a. TVar a -> a -> STM ()
writeTVar TVar (LRUNode s)
nodeTVar LRUNode s
node {
nodeValue :: ByteString
nodeValue = ByteString -> ByteString
BL.toStrict (forall a. ToJSON a => a -> ByteString
encode (Int
nforall a. Num a => a -> a -> a
+Int
1)),
nodeExpiry :: Maybe TimeSpec
nodeExpiry = Maybe TimeSpec
newExpiry
}
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
| Bool
otherwise -> do
forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache) TVar (LRUNode s)
nodeTVar
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
Maybe Int
_ -> do
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 <- forall key value. Map key value -> STM Int
Map.size (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
sz forall a. Ord a => a -> a -> Bool
>= forall s. TinyLRUCache s -> Int
lruCap TinyLRUCache s
cache) forall a b. (a -> b) -> a -> b
$ forall s. TinyLRUCache s -> STM ()
evictLRU TinyLRUCache s
cache
TVar (LRUNode s)
nodeTVar <- forall s.
TimeSpec
-> Int
-> TinyLRUCache s
-> Text
-> ByteString
-> STM (TVar (LRUNode s))
addToFront TimeSpec
now Int
period TinyLRUCache s
cache Text
key (ByteString -> ByteString
BL.toStrict (forall a. ToJSON a => a -> ByteString
encode (Int
1 :: Int)))
forall key value.
Hashable key =>
value -> key -> Map key value -> STM ()
Map.insert TVar (LRUNode s)
nodeTVar Text
key (forall s. TinyLRUCache s -> Map Text (TVar (LRUNode s))
lruCache TinyLRUCache s
cache)
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 = forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
removeNode (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 = forall s. TVar (LRUList s) -> TVar (LRUNode s) -> STM ()
moveToFront (forall s. TinyLRUCache s -> TVar (LRUList s)
lruList TinyLRUCache s
cache)