{- | If you've provided a @TrimScheme@ in your structure, adding content (via prepend/append) will trim your list
to preserve this, prioritizing newest content - i.e., prepend commands will result in content
being trimmed from the end on overflow, and append commands will result in content trimmed from
the front on overflow.

-}

module HLRDB.Structures.List
       (
         HLRDB.Structures.List.lrange
       , lprepend
       , lappend
       , HLRDB.Structures.List.lpop
       , HLRDB.Structures.List.lrem
       , HLRDB.Structures.List.llen
       -- * Other commands
       -- | The following commands are available in Redis, but are recommended to use only with caution, due to their behavior being either "unhaskell-ey" or downright exotic.
       , HLRDB.Structures.List.rpop
       , HLRDB.Structures.List.rpoplpush
       , HLRDB.Structures.List.blpop
       , HLRDB.Structures.List.brpop
       , HLRDB.Structures.List.brpoplpush
       ) where

import Database.Redis as Redis
import HLRDB.Primitives.Redis
import HLRDB.Internal
import Data.Maybe (fromJust)


-- | Retrieve a range of elements. Endpoints are inclusive, just as with Haskell's [ 1 .. 5 ] notation.
lrange :: MonadRedis m => RedisList a b -> a -> Integer -> Integer -> m [ b ]
lrange :: RedisList a b -> a -> Integer -> Integer -> m [b]
lrange p :: RedisList a b
p@(RList (E a -> ByteString
_ b -> Identity ByteString
_ Identity ByteString -> b
d) Maybe TrimScheme
_) a
k Integer
i =
    (([ByteString] -> [b]) -> m [ByteString] -> m [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([ByteString] -> [b]) -> m [ByteString] -> m [b])
-> ((ByteString -> b) -> [ByteString] -> [b])
-> (ByteString -> b)
-> m [ByteString]
-> m [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> b) -> [ByteString] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) (Identity ByteString -> b
d (Identity ByteString -> b)
-> (ByteString -> Identity ByteString) -> ByteString -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Identity ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure)
  (m [ByteString] -> m [b])
-> (Integer -> m [ByteString]) -> Integer -> m [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Redis (Either Reply [ByteString]) -> m [ByteString]
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap
  (Redis (Either Reply [ByteString]) -> m [ByteString])
-> (Integer -> Redis (Either Reply [ByteString]))
-> Integer
-> m [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString
-> Integer -> Integer -> Redis (Either Reply [ByteString])
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> Integer -> Integer -> m (f [ByteString])
Redis.lrange (RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p a
k) Integer
i

-- | Append items to the end of a list
lappend :: (MonadRedis m , Traversable t) => RedisList a b -> a -> t b -> m ()
lappend :: RedisList a b -> a -> t b -> m ()
lappend = Bool -> RedisList a b -> a -> t b -> m ()
forall (m :: * -> *) (t :: * -> *) a b.
(MonadRedis m, Traversable t) =>
Bool -> RedisList a b -> a -> t b -> m ()
addItem Bool
True

-- | Prepend items to the front of a list
lprepend :: (MonadRedis m , Traversable t) => RedisList a b -> a -> t b -> m ()
lprepend :: RedisList a b -> a -> t b -> m ()
lprepend = Bool -> RedisList a b -> a -> t b -> m ()
forall (m :: * -> *) (t :: * -> *) a b.
(MonadRedis m, Traversable t) =>
Bool -> RedisList a b -> a -> t b -> m ()
addItem Bool
False

addItem :: (MonadRedis m , Traversable t) => Bool -> RedisList a b -> a -> t b -> m ()
addItem :: Bool -> RedisList a b -> a -> t b -> m ()
addItem Bool
toTheEnd p :: RedisList a b
p@(RList (E a -> ByteString
_ b -> Identity ByteString
e Identity ByteString -> b
_) Maybe TrimScheme
trimScheme) a
k t b
bs' =
  let bs :: [b]
bs = (b -> [b] -> [b]) -> [b] -> t b -> [b]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (:) [] t b
bs' in
  case [b]
bs of
  [] -> () -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  [b]
_ -> do
       let method :: ByteString -> [ByteString] -> Redis (Either Reply Integer)
method = if Bool
toTheEnd then ByteString -> [ByteString] -> Redis (Either Reply Integer)
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> [ByteString] -> m (f Integer)
rpush else ByteString -> [ByteString] -> Redis (Either Reply Integer)
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> [ByteString] -> m (f Integer)
lpush
       let key :: ByteString
key = RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p a
k
       Integer
itemCount <- Redis (Either Reply Integer) -> m Integer
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap (Redis (Either Reply Integer) -> m Integer)
-> Redis (Either Reply Integer) -> m Integer
forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString] -> Redis (Either Reply Integer)
method ByteString
key ((b -> ByteString) -> [b] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Identity ByteString -> ByteString
forall a. Identity a -> a
runIdentity (Identity ByteString -> ByteString)
-> (b -> Identity ByteString) -> b -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Identity ByteString
e) [b]
bs)
       case Maybe TrimScheme
trimScheme of
         Just (TrimScheme Integer
maxItemCount Double
prob) -> (Maybe () -> ()) -> m (Maybe ()) -> m ()
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (() -> Maybe () -> ()
forall a b. a -> b -> a
const ()) (m (Maybe ()) -> m ()) -> m (Maybe ()) -> m ()
forall a b. (a -> b) -> a -> b
$ Redis (Maybe ()) -> m (Maybe ())
forall (m :: * -> *) a. MonadRedis m => Redis a -> m a
liftRedis (Redis (Maybe ()) -> m (Maybe ()))
-> Redis (Maybe ()) -> m (Maybe ())
forall a b. (a -> b) -> a -> b
$ Double -> Redis () -> Redis (Maybe ())
forall (m :: * -> *) a. MonadIO m => Double -> m a -> m (Maybe a)
probIO Double
prob (Redis () -> Redis (Maybe ())) -> Redis () -> Redis (Maybe ())
forall a b. (a -> b) -> a -> b
$
           if Integer
itemCount Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
maxItemCount
              then Redis Status -> Redis ()
forall (f :: * -> *) a. Functor f => f a -> f ()
ignore (Redis Status -> Redis ()) -> Redis Status -> Redis ()
forall a b. (a -> b) -> a -> b
$ if Bool
toTheEnd
                   then Redis (Either Reply Status) -> Redis Status
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap (Redis (Either Reply Status) -> Redis Status)
-> Redis (Either Reply Status) -> Redis Status
forall a b. (a -> b) -> a -> b
$ ByteString -> Integer -> Integer -> Redis (Either Reply Status)
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> Integer -> Integer -> m (f Status)
ltrim ByteString
key (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer) -> Int -> Integer
forall a b. (a -> b) -> a -> b
$ [b] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [b]
bs) (-Integer
1)
                   else Redis (Either Reply Status) -> Redis Status
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap (Redis (Either Reply Status) -> Redis Status)
-> Redis (Either Reply Status) -> Redis Status
forall a b. (a -> b) -> a -> b
$ ByteString -> Integer -> Integer -> Redis (Either Reply Status)
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> Integer -> Integer -> m (f Status)
ltrim ByteString
key Integer
0 (Integer
maxItemCount Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)
              else () -> Redis ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
         Maybe TrimScheme
Nothing -> () -> m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

-- | Remove an item from the list. You should ensure that any Eq instance in Haskell respects the induced equality by your encoding scheme, as Redis will use the latter.
lrem :: MonadRedis m => RedisList a b -> a -> b -> m ()
lrem :: RedisList a b -> a -> b -> m ()
lrem p :: RedisList a b
p@(RList (E a -> ByteString
_ b -> Identity ByteString
e Identity ByteString -> b
_) Maybe TrimScheme
_) a
k =
    m Integer -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
ignore
  (m Integer -> m ()) -> (b -> m Integer) -> b -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Redis (Either Reply Integer) -> m Integer
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap
  (Redis (Either Reply Integer) -> m Integer)
-> (b -> Redis (Either Reply Integer)) -> b -> m Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Integer -> ByteString -> Redis (Either Reply Integer)
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> Integer -> ByteString -> m (f Integer)
Redis.lrem (RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p a
k) Integer
0
  (ByteString -> Redis (Either Reply Integer))
-> (b -> ByteString) -> b -> Redis (Either Reply Integer)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identity ByteString -> ByteString
forall a. Identity a -> a
runIdentity
  (Identity ByteString -> ByteString)
-> (b -> Identity ByteString) -> b -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Identity ByteString
e

-- | Retrieve the length of a list.
llen :: MonadRedis m => RedisList a b -> a -> m Integer
llen :: RedisList a b -> a -> m Integer
llen RedisList a b
p =
    Redis (Either Reply Integer) -> m Integer
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap
  (Redis (Either Reply Integer) -> m Integer)
-> (a -> Redis (Either Reply Integer)) -> a -> m Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Redis (Either Reply Integer)
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> m (f Integer)
Redis.llen
  (ByteString -> Redis (Either Reply Integer))
-> (a -> ByteString) -> a -> Redis (Either Reply Integer)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p

-- | Remove and return an item from the head of the list.
lpop :: MonadRedis m => RedisList a b -> a -> m (Maybe b)
lpop :: RedisList a b -> a -> m (Maybe b)
lpop p :: RedisList a b
p@(RList (E a -> ByteString
_ b -> Identity ByteString
_ Identity ByteString -> b
d) Maybe TrimScheme
_) =
    ((Maybe ByteString -> Maybe b)
-> m (Maybe ByteString) -> m (Maybe b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Maybe ByteString -> Maybe b)
 -> m (Maybe ByteString) -> m (Maybe b))
-> ((ByteString -> b) -> Maybe ByteString -> Maybe b)
-> (ByteString -> b)
-> m (Maybe ByteString)
-> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> b) -> Maybe ByteString -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) (Identity ByteString -> b
d (Identity ByteString -> b)
-> (ByteString -> Identity ByteString) -> ByteString -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Identity ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure)
  (m (Maybe ByteString) -> m (Maybe b))
-> (a -> m (Maybe ByteString)) -> a -> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Redis (Either Reply (Maybe ByteString)) -> m (Maybe ByteString)
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap
  (Redis (Either Reply (Maybe ByteString)) -> m (Maybe ByteString))
-> (a -> Redis (Either Reply (Maybe ByteString)))
-> a
-> m (Maybe ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Redis (Either Reply (Maybe ByteString))
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> m (f (Maybe ByteString))
Redis.lpop
  (ByteString -> Redis (Either Reply (Maybe ByteString)))
-> (a -> ByteString)
-> a
-> Redis (Either Reply (Maybe ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p

-- | Remove and return an item from the end of the list.
rpop :: MonadRedis m => RedisList a b -> a -> m (Maybe b)
rpop :: RedisList a b -> a -> m (Maybe b)
rpop p :: RedisList a b
p@(RList (E a -> ByteString
_ b -> Identity ByteString
_ Identity ByteString -> b
d) Maybe TrimScheme
_) =
    ((Maybe ByteString -> Maybe b)
-> m (Maybe ByteString) -> m (Maybe b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Maybe ByteString -> Maybe b)
 -> m (Maybe ByteString) -> m (Maybe b))
-> ((ByteString -> b) -> Maybe ByteString -> Maybe b)
-> (ByteString -> b)
-> m (Maybe ByteString)
-> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> b) -> Maybe ByteString -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) (Identity ByteString -> b
d (Identity ByteString -> b)
-> (ByteString -> Identity ByteString) -> ByteString -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Identity ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure)
  (m (Maybe ByteString) -> m (Maybe b))
-> (a -> m (Maybe ByteString)) -> a -> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Redis (Either Reply (Maybe ByteString)) -> m (Maybe ByteString)
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap
  (Redis (Either Reply (Maybe ByteString)) -> m (Maybe ByteString))
-> (a -> Redis (Either Reply (Maybe ByteString)))
-> a
-> m (Maybe ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Redis (Either Reply (Maybe ByteString))
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> m (f (Maybe ByteString))
Redis.rpop
  (ByteString -> Redis (Either Reply (Maybe ByteString)))
-> (a -> ByteString)
-> a
-> Redis (Either Reply (Maybe ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p

-- | Remove and return an item from the first list and prepend it to the second list.
rpoplpush :: MonadRedis m => RedisList a b -> a -> a -> m (Maybe b)
rpoplpush :: RedisList a b -> a -> a -> m (Maybe b)
rpoplpush p :: RedisList a b
p@(RList (E a -> ByteString
_ b -> Identity ByteString
_ Identity ByteString -> b
d) Maybe TrimScheme
_) a
s =
    ((Maybe ByteString -> Maybe b)
-> m (Maybe ByteString) -> m (Maybe b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Maybe ByteString -> Maybe b)
 -> m (Maybe ByteString) -> m (Maybe b))
-> ((ByteString -> b) -> Maybe ByteString -> Maybe b)
-> (ByteString -> b)
-> m (Maybe ByteString)
-> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> b) -> Maybe ByteString -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) (Identity ByteString -> b
d (Identity ByteString -> b)
-> (ByteString -> Identity ByteString) -> ByteString -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Identity ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure)
  (m (Maybe ByteString) -> m (Maybe b))
-> (a -> m (Maybe ByteString)) -> a -> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Redis (Either Reply (Maybe ByteString)) -> m (Maybe ByteString)
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap
  (Redis (Either Reply (Maybe ByteString)) -> m (Maybe ByteString))
-> (a -> Redis (Either Reply (Maybe ByteString)))
-> a
-> m (Maybe ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString -> Redis (Either Reply (Maybe ByteString))
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> ByteString -> m (f (Maybe ByteString))
Redis.rpoplpush (RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p a
s)
  (ByteString -> Redis (Either Reply (Maybe ByteString)))
-> (a -> ByteString)
-> a
-> Redis (Either Reply (Maybe ByteString))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p

-- | Blocking variant of rpoplpush
brpoplpush :: MonadRedis m => RedisList a b -> a -> a -> Integer -> m (Maybe b)
brpoplpush :: RedisList a b -> a -> a -> Integer -> m (Maybe b)
brpoplpush p :: RedisList a b
p@(RList (E a -> ByteString
_ b -> Identity ByteString
_ Identity ByteString -> b
d) Maybe TrimScheme
_) a
s a
e =
    ((Maybe ByteString -> Maybe b)
-> m (Maybe ByteString) -> m (Maybe b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Maybe ByteString -> Maybe b)
 -> m (Maybe ByteString) -> m (Maybe b))
-> ((ByteString -> b) -> Maybe ByteString -> Maybe b)
-> (ByteString -> b)
-> m (Maybe ByteString)
-> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> b) -> Maybe ByteString -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) (Identity ByteString -> b
d (Identity ByteString -> b)
-> (ByteString -> Identity ByteString) -> ByteString -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Identity ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure)
  (m (Maybe ByteString) -> m (Maybe b))
-> (Integer -> m (Maybe ByteString)) -> Integer -> m (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Redis (Either Reply (Maybe ByteString)) -> m (Maybe ByteString)
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap
  (Redis (Either Reply (Maybe ByteString)) -> m (Maybe ByteString))
-> (Integer -> Redis (Either Reply (Maybe ByteString)))
-> Integer
-> m (Maybe ByteString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString
-> ByteString -> Integer -> Redis (Either Reply (Maybe ByteString))
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
ByteString -> ByteString -> Integer -> m (f (Maybe ByteString))
Redis.brpoplpush (RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p a
s) (RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p a
e)

-- | Pop the first available value from a set of lists; if none is available, block the connection (!) until either the specified timeout completes, returning nothing, or until a value becomes available, returning the value and the key of the list in which it was added, whichever happens first. If multiple clients are waiting for an item from the same list, the one who has been waiting the longest will be given the item. If no keys are given, the command returns immediately with Nothing.
blpop :: (MonadRedis m , Traversable t) => RedisList a b -> t a -> Integer -> m (Maybe (a , b))
blpop :: RedisList a b -> t a -> Integer -> m (Maybe (a, b))
blpop p :: RedisList a b
p@(RList (E a -> ByteString
e b -> Identity ByteString
_ Identity ByteString -> b
d) Maybe TrimScheme
_) t a
ts Integer
t = case (a -> [(ByteString, a)] -> [(ByteString, a)])
-> [(ByteString, a)] -> t a -> [(ByteString, a)]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
x [(ByteString, a)]
a -> (a -> ByteString
e a
x , a
x) (ByteString, a) -> [(ByteString, a)] -> [(ByteString, a)]
forall a. a -> [a] -> [a]
: [(ByteString, a)]
a) [] t a
ts of
  [] -> Maybe (a, b) -> m (Maybe (a, b))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (a, b)
forall a. Maybe a
Nothing
  [(ByteString, a)]
xs ->
    let f :: (ByteString, ByteString) -> (a, b)
f (ByteString
x , ByteString
b) = (Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust (ByteString -> [(ByteString, a)] -> Maybe a
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup ByteString
x [(ByteString, a)]
xs) , (Identity ByteString -> b
d (Identity ByteString -> b)
-> (ByteString -> Identity ByteString) -> ByteString -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Identity ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure) ByteString
b) in
    ((m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b)))
-> (Redis (Either Reply (Maybe (ByteString, ByteString)))
    -> m (Maybe (ByteString, ByteString)))
-> Redis (Either Reply (Maybe (ByteString, ByteString)))
-> m (Maybe (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b)))
 -> (Redis (Either Reply (Maybe (ByteString, ByteString)))
     -> m (Maybe (ByteString, ByteString)))
 -> Redis (Either Reply (Maybe (ByteString, ByteString)))
 -> m (Maybe (a, b)))
-> (((ByteString, ByteString) -> (a, b))
    -> m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b)))
-> ((ByteString, ByteString) -> (a, b))
-> (Redis (Either Reply (Maybe (ByteString, ByteString)))
    -> m (Maybe (ByteString, ByteString)))
-> Redis (Either Reply (Maybe (ByteString, ByteString)))
-> m (Maybe (a, b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe (ByteString, ByteString) -> Maybe (a, b))
-> m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Maybe (ByteString, ByteString) -> Maybe (a, b))
 -> m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b)))
-> (((ByteString, ByteString) -> (a, b))
    -> Maybe (ByteString, ByteString) -> Maybe (a, b))
-> ((ByteString, ByteString) -> (a, b))
-> m (Maybe (ByteString, ByteString))
-> m (Maybe (a, b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ByteString, ByteString) -> (a, b))
-> Maybe (ByteString, ByteString) -> Maybe (a, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) (ByteString, ByteString) -> (a, b)
f Redis (Either Reply (Maybe (ByteString, ByteString)))
-> m (Maybe (ByteString, ByteString))
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap (Redis (Either Reply (Maybe (ByteString, ByteString)))
 -> m (Maybe (a, b)))
-> Redis (Either Reply (Maybe (ByteString, ByteString)))
-> m (Maybe (a, b))
forall a b. (a -> b) -> a -> b
$ [ByteString]
-> Integer -> Redis (Either Reply (Maybe (ByteString, ByteString)))
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
[ByteString] -> Integer -> m (f (Maybe (ByteString, ByteString)))
Redis.blpop (RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p (a -> ByteString)
-> ((ByteString, a) -> a) -> (ByteString, a) -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString, a) -> a
forall a b. (a, b) -> b
snd ((ByteString, a) -> ByteString)
-> [(ByteString, a)] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(ByteString, a)]
xs) Integer
t

-- | Similar to blpop, but popping from the right.
brpop :: (MonadRedis m , Traversable t) => RedisList a b -> t a -> Integer -> m (Maybe (a , b))
brpop :: RedisList a b -> t a -> Integer -> m (Maybe (a, b))
brpop p :: RedisList a b
p@(RList (E a -> ByteString
e b -> Identity ByteString
_ Identity ByteString -> b
d) Maybe TrimScheme
_) t a
ts Integer
t = case (a -> [(ByteString, a)] -> [(ByteString, a)])
-> [(ByteString, a)] -> t a -> [(ByteString, a)]
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
x [(ByteString, a)]
a -> (a -> ByteString
e a
x , a
x) (ByteString, a) -> [(ByteString, a)] -> [(ByteString, a)]
forall a. a -> [a] -> [a]
: [(ByteString, a)]
a) [] t a
ts of
  [] -> Maybe (a, b) -> m (Maybe (a, b))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (a, b)
forall a. Maybe a
Nothing
  [(ByteString, a)]
xs ->
    let f :: (ByteString, ByteString) -> (a, b)
f (ByteString
x , ByteString
b) = (Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust (ByteString -> [(ByteString, a)] -> Maybe a
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup ByteString
x [(ByteString, a)]
xs) , (Identity ByteString -> b
d (Identity ByteString -> b)
-> (ByteString -> Identity ByteString) -> ByteString -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Identity ByteString
forall (f :: * -> *) a. Applicative f => a -> f a
pure) ByteString
b) in
    ((m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b)))
-> (Redis (Either Reply (Maybe (ByteString, ByteString)))
    -> m (Maybe (ByteString, ByteString)))
-> Redis (Either Reply (Maybe (ByteString, ByteString)))
-> m (Maybe (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b)))
 -> (Redis (Either Reply (Maybe (ByteString, ByteString)))
     -> m (Maybe (ByteString, ByteString)))
 -> Redis (Either Reply (Maybe (ByteString, ByteString)))
 -> m (Maybe (a, b)))
-> (((ByteString, ByteString) -> (a, b))
    -> m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b)))
-> ((ByteString, ByteString) -> (a, b))
-> (Redis (Either Reply (Maybe (ByteString, ByteString)))
    -> m (Maybe (ByteString, ByteString)))
-> Redis (Either Reply (Maybe (ByteString, ByteString)))
-> m (Maybe (a, b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe (ByteString, ByteString) -> Maybe (a, b))
-> m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Maybe (ByteString, ByteString) -> Maybe (a, b))
 -> m (Maybe (ByteString, ByteString)) -> m (Maybe (a, b)))
-> (((ByteString, ByteString) -> (a, b))
    -> Maybe (ByteString, ByteString) -> Maybe (a, b))
-> ((ByteString, ByteString) -> (a, b))
-> m (Maybe (ByteString, ByteString))
-> m (Maybe (a, b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ByteString, ByteString) -> (a, b))
-> Maybe (ByteString, ByteString) -> Maybe (a, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap) (ByteString, ByteString) -> (a, b)
f Redis (Either Reply (Maybe (ByteString, ByteString)))
-> m (Maybe (ByteString, ByteString))
forall (m :: * -> *) a.
MonadRedis m =>
Redis (Either Reply a) -> m a
unwrap (Redis (Either Reply (Maybe (ByteString, ByteString)))
 -> m (Maybe (a, b)))
-> Redis (Either Reply (Maybe (ByteString, ByteString)))
-> m (Maybe (a, b))
forall a b. (a -> b) -> a -> b
$ [ByteString]
-> Integer -> Redis (Either Reply (Maybe (ByteString, ByteString)))
forall (m :: * -> *) (f :: * -> *).
RedisCtx m f =>
[ByteString] -> Integer -> m (f (Maybe (ByteString, ByteString)))
Redis.brpop (RedisList a b -> a -> ByteString
forall v a b. RedisStructure v a b -> a -> ByteString
primKey RedisList a b
p (a -> ByteString)
-> ((ByteString, a) -> a) -> (ByteString, a) -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString, a) -> a
forall a b. (a, b) -> b
snd ((ByteString, a) -> ByteString)
-> [(ByteString, a)] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(ByteString, a)]
xs) Integer
t