packages feed

hedis 0.12.14 → 0.12.15

raw patch · 3 files changed

+224/−1 lines, 3 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Database.Redis.Sentinel: ApproxMaxlen :: Integer -> TrimOpts
+ Database.Redis.Sentinel: Asc :: SortOrder
+ Database.Redis.Sentinel: Bulk :: Maybe ByteString -> Reply
+ Database.Redis.Sentinel: ConnInfo :: HostName -> PortID -> Maybe ByteString -> Integer -> Int -> NominalDiffTime -> Maybe NominalDiffTime -> Maybe ClientParams -> ConnectInfo
+ Database.Redis.Sentinel: ConnectAuthError :: Reply -> ConnectError
+ Database.Redis.Sentinel: ConnectSelectError :: Reply -> ConnectError
+ Database.Redis.Sentinel: ConnectTimeout :: ConnectPhase -> ConnectTimeout
+ Database.Redis.Sentinel: ConnectionLost :: ConnectionLostException
+ Database.Redis.Sentinel: Desc :: SortOrder
+ Database.Redis.Sentinel: Error :: ByteString -> Reply
+ Database.Redis.Sentinel: Excl :: a -> RangeLex a
+ Database.Redis.Sentinel: Hash :: RedisType
+ Database.Redis.Sentinel: Incl :: a -> RangeLex a
+ Database.Redis.Sentinel: Integer :: Integer -> Reply
+ Database.Redis.Sentinel: List :: RedisType
+ Database.Redis.Sentinel: Max :: Aggregate
+ Database.Redis.Sentinel: Maxlen :: Integer -> TrimOpts
+ Database.Redis.Sentinel: Maxr :: RangeLex a
+ Database.Redis.Sentinel: Message :: ByteString -> Message
+ Database.Redis.Sentinel: MigrateOpts :: Bool -> Bool -> MigrateOpts
+ Database.Redis.Sentinel: Min :: Aggregate
+ Database.Redis.Sentinel: Minr :: RangeLex a
+ Database.Redis.Sentinel: MultiBulk :: Maybe [Reply] -> Reply
+ Database.Redis.Sentinel: NoArgs :: TrimOpts
+ Database.Redis.Sentinel: NoSentinels :: NonEmpty (HostName, PortID) -> RedisSentinelException
+ Database.Redis.Sentinel: None :: RedisType
+ Database.Redis.Sentinel: Nx :: Condition
+ Database.Redis.Sentinel: Ok :: Status
+ Database.Redis.Sentinel: PMessage :: ByteString -> Message
+ Database.Redis.Sentinel: Pong :: Status
+ Database.Redis.Sentinel: PortNumber :: PortNumber -> PortID
+ Database.Redis.Sentinel: ScanOpts :: Maybe ByteString -> Maybe Integer -> ScanOpts
+ Database.Redis.Sentinel: SentinelConnectInfo :: NonEmpty (HostName, PortID) -> ByteString -> ConnectInfo -> SentinelConnectInfo
+ Database.Redis.Sentinel: Set :: RedisType
+ Database.Redis.Sentinel: SetOpts :: Maybe Integer -> Maybe Integer -> Maybe Condition -> SetOpts
+ Database.Redis.Sentinel: SingleLine :: ByteString -> Reply
+ Database.Redis.Sentinel: Slowlog :: Integer -> Integer -> Integer -> [ByteString] -> Maybe ByteString -> Maybe ByteString -> Slowlog
+ Database.Redis.Sentinel: SortOpts :: Maybe ByteString -> (Integer, Integer) -> [ByteString] -> SortOrder -> Bool -> SortOpts
+ Database.Redis.Sentinel: Status :: ByteString -> Status
+ Database.Redis.Sentinel: StreamsRecord :: ByteString -> [(ByteString, ByteString)] -> StreamsRecord
+ Database.Redis.Sentinel: String :: RedisType
+ Database.Redis.Sentinel: Sum :: Aggregate
+ Database.Redis.Sentinel: TxAborted :: TxResult a
+ Database.Redis.Sentinel: TxError :: String -> TxResult a
+ Database.Redis.Sentinel: TxSuccess :: a -> TxResult a
+ Database.Redis.Sentinel: UnixSocket :: String -> PortID
+ Database.Redis.Sentinel: XClaimOpts :: Maybe Integer -> Maybe Integer -> Maybe Integer -> Bool -> XClaimOpts
+ Database.Redis.Sentinel: XInfoConsumersResponse :: ByteString -> Integer -> Integer -> XInfoConsumersResponse
+ Database.Redis.Sentinel: XInfoGroupsResponse :: ByteString -> Integer -> Integer -> ByteString -> XInfoGroupsResponse
+ Database.Redis.Sentinel: XInfoStreamResponse :: Integer -> Integer -> Integer -> Integer -> ByteString -> StreamsRecord -> StreamsRecord -> XInfoStreamResponse
+ Database.Redis.Sentinel: XPendingDetailRecord :: ByteString -> ByteString -> Integer -> Integer -> XPendingDetailRecord
+ Database.Redis.Sentinel: XPendingSummaryResponse :: Integer -> ByteString -> ByteString -> [(ByteString, Integer)] -> XPendingSummaryResponse
+ Database.Redis.Sentinel: XReadOpts :: Maybe Integer -> Maybe Integer -> XReadOpts
+ Database.Redis.Sentinel: XReadResponse :: ByteString -> [StreamsRecord] -> XReadResponse
+ Database.Redis.Sentinel: Xx :: Condition
+ Database.Redis.Sentinel: ZSet :: RedisType
+ Database.Redis.Sentinel: ZaddOpts :: Maybe Condition -> Bool -> Bool -> ZaddOpts
+ Database.Redis.Sentinel: [block] :: XReadOpts -> Maybe Integer
+ Database.Redis.Sentinel: [connectAuth] :: ConnectInfo -> Maybe ByteString
+ Database.Redis.Sentinel: [connectBaseInfo] :: SentinelConnectInfo -> ConnectInfo
+ Database.Redis.Sentinel: [connectDatabase] :: ConnectInfo -> Integer
+ Database.Redis.Sentinel: [connectHost] :: ConnectInfo -> HostName
+ Database.Redis.Sentinel: [connectMasterName] :: SentinelConnectInfo -> ByteString
+ Database.Redis.Sentinel: [connectMaxConnections] :: ConnectInfo -> Int
+ Database.Redis.Sentinel: [connectMaxIdleTime] :: ConnectInfo -> NominalDiffTime
+ Database.Redis.Sentinel: [connectPort] :: ConnectInfo -> PortID
+ Database.Redis.Sentinel: [connectSentinels] :: SentinelConnectInfo -> NonEmpty (HostName, PortID)
+ Database.Redis.Sentinel: [connectTLSParams] :: ConnectInfo -> Maybe ClientParams
+ Database.Redis.Sentinel: [connectTimeout] :: ConnectInfo -> Maybe NominalDiffTime
+ Database.Redis.Sentinel: [consumer] :: XPendingDetailRecord -> ByteString
+ Database.Redis.Sentinel: [keyValues] :: StreamsRecord -> [(ByteString, ByteString)]
+ Database.Redis.Sentinel: [largestPendingMessageId] :: XPendingSummaryResponse -> ByteString
+ Database.Redis.Sentinel: [messageId] :: XPendingDetailRecord -> ByteString
+ Database.Redis.Sentinel: [migrateCopy] :: MigrateOpts -> Bool
+ Database.Redis.Sentinel: [migrateReplace] :: MigrateOpts -> Bool
+ Database.Redis.Sentinel: [millisSinceLastDelivered] :: XPendingDetailRecord -> Integer
+ Database.Redis.Sentinel: [msgChannel, msgMessage] :: Message -> ByteString
+ Database.Redis.Sentinel: [msgPattern, msgChannel, msgMessage] :: Message -> ByteString
+ Database.Redis.Sentinel: [numPendingMessagesByconsumer] :: XPendingSummaryResponse -> [(ByteString, Integer)]
+ Database.Redis.Sentinel: [numPendingMessages] :: XPendingSummaryResponse -> Integer
+ Database.Redis.Sentinel: [numTimesDelivered] :: XPendingDetailRecord -> Integer
+ Database.Redis.Sentinel: [recordCount] :: XReadOpts -> Maybe Integer
+ Database.Redis.Sentinel: [recordId] :: StreamsRecord -> ByteString
+ Database.Redis.Sentinel: [records] :: XReadResponse -> [StreamsRecord]
+ Database.Redis.Sentinel: [scanCount] :: ScanOpts -> Maybe Integer
+ Database.Redis.Sentinel: [scanMatch] :: ScanOpts -> Maybe ByteString
+ Database.Redis.Sentinel: [setCondition] :: SetOpts -> Maybe Condition
+ Database.Redis.Sentinel: [setMilliseconds] :: SetOpts -> Maybe Integer
+ Database.Redis.Sentinel: [setSeconds] :: SetOpts -> Maybe Integer
+ Database.Redis.Sentinel: [slowlogClientIpAndPort] :: Slowlog -> Maybe ByteString
+ Database.Redis.Sentinel: [slowlogClientName] :: Slowlog -> Maybe ByteString
+ Database.Redis.Sentinel: [slowlogCmd] :: Slowlog -> [ByteString]
+ Database.Redis.Sentinel: [slowlogId] :: Slowlog -> Integer
+ Database.Redis.Sentinel: [slowlogMicros] :: Slowlog -> Integer
+ Database.Redis.Sentinel: [slowlogTimestamp] :: Slowlog -> Integer
+ Database.Redis.Sentinel: [smallestPendingMessageId] :: XPendingSummaryResponse -> ByteString
+ Database.Redis.Sentinel: [sortAlpha] :: SortOpts -> Bool
+ Database.Redis.Sentinel: [sortBy] :: SortOpts -> Maybe ByteString
+ Database.Redis.Sentinel: [sortGet] :: SortOpts -> [ByteString]
+ Database.Redis.Sentinel: [sortLimit] :: SortOpts -> (Integer, Integer)
+ Database.Redis.Sentinel: [sortOrder] :: SortOpts -> SortOrder
+ Database.Redis.Sentinel: [stream] :: XReadResponse -> ByteString
+ Database.Redis.Sentinel: [xclaimForce] :: XClaimOpts -> Bool
+ Database.Redis.Sentinel: [xclaimIdle] :: XClaimOpts -> Maybe Integer
+ Database.Redis.Sentinel: [xclaimRetryCount] :: XClaimOpts -> Maybe Integer
+ Database.Redis.Sentinel: [xclaimTime] :: XClaimOpts -> Maybe Integer
+ Database.Redis.Sentinel: [xinfoConsumerIdleTime] :: XInfoConsumersResponse -> Integer
+ Database.Redis.Sentinel: [xinfoConsumerName] :: XInfoConsumersResponse -> ByteString
+ Database.Redis.Sentinel: [xinfoConsumerNumPendingMessages] :: XInfoConsumersResponse -> Integer
+ Database.Redis.Sentinel: [xinfoGroupsGroupName] :: XInfoGroupsResponse -> ByteString
+ Database.Redis.Sentinel: [xinfoGroupsLastDeliveredMessageId] :: XInfoGroupsResponse -> ByteString
+ Database.Redis.Sentinel: [xinfoGroupsNumConsumers] :: XInfoGroupsResponse -> Integer
+ Database.Redis.Sentinel: [xinfoGroupsNumPendingMessages] :: XInfoGroupsResponse -> Integer
+ Database.Redis.Sentinel: [xinfoStreamFirstEntry] :: XInfoStreamResponse -> StreamsRecord
+ Database.Redis.Sentinel: [xinfoStreamLastEntryId] :: XInfoStreamResponse -> ByteString
+ Database.Redis.Sentinel: [xinfoStreamLastEntry] :: XInfoStreamResponse -> StreamsRecord
+ Database.Redis.Sentinel: [xinfoStreamLength] :: XInfoStreamResponse -> Integer
+ Database.Redis.Sentinel: [xinfoStreamNumGroups] :: XInfoStreamResponse -> Integer
+ Database.Redis.Sentinel: [xinfoStreamRadixTreeKeys] :: XInfoStreamResponse -> Integer
+ Database.Redis.Sentinel: [xinfoStreamRadixTreeNodes] :: XInfoStreamResponse -> Integer
+ Database.Redis.Sentinel: [zaddChange] :: ZaddOpts -> Bool
+ Database.Redis.Sentinel: [zaddCondition] :: ZaddOpts -> Maybe Condition
+ Database.Redis.Sentinel: [zaddIncrement] :: ZaddOpts -> Bool
+ Database.Redis.Sentinel: addChannels :: MonadIO m => PubSubController -> [(RedisChannel, MessageCallback)] -> [(RedisPChannel, PMessageCallback)] -> m UnregisterCallbacksAction
+ Database.Redis.Sentinel: addChannelsAndWait :: MonadIO m => PubSubController -> [(RedisChannel, MessageCallback)] -> [(RedisPChannel, PMessageCallback)] -> m UnregisterCallbacksAction
+ Database.Redis.Sentinel: append :: RedisCtx m f => ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: auth :: ByteString -> Redis (Either Reply Status)
+ Database.Redis.Sentinel: bgrewriteaof :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: bgsave :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: bitcount :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: bitcountRange :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f Integer)
+ Database.Redis.Sentinel: bitopAnd :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: bitopNot :: RedisCtx m f => ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: bitopOr :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: bitopXor :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: bitpos :: RedisCtx m f => ByteString -> Integer -> Integer -> Integer -> m (f Integer)
+ Database.Redis.Sentinel: blpop :: RedisCtx m f => [ByteString] -> Integer -> m (f (Maybe (ByteString, ByteString)))
+ Database.Redis.Sentinel: brpop :: RedisCtx m f => [ByteString] -> Integer -> m (f (Maybe (ByteString, ByteString)))
+ Database.Redis.Sentinel: brpoplpush :: RedisCtx m f => ByteString -> ByteString -> Integer -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: checkedConnect :: ConnectInfo -> IO Connection
+ Database.Redis.Sentinel: class (Monad m) => MonadRedis m
+ Database.Redis.Sentinel: class (MonadRedis m) => RedisCtx m f | m -> f
+ Database.Redis.Sentinel: class RedisResult a
+ Database.Redis.Sentinel: clientGetname :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: clientList :: RedisCtx m f => m (f [ByteString])
+ Database.Redis.Sentinel: clientPause :: RedisCtx m f => Integer -> m (f Status)
+ Database.Redis.Sentinel: clientReply :: RedisCtx m f => ReplyMode -> m (f Bool)
+ Database.Redis.Sentinel: clientSetname :: RedisCtx m f => ByteString -> m (f ByteString)
+ Database.Redis.Sentinel: commandCount :: RedisCtx m f => m (f Integer)
+ Database.Redis.Sentinel: commandInfo :: RedisCtx m f => [ByteString] -> m (f [ByteString])
+ Database.Redis.Sentinel: configGet :: RedisCtx m f => ByteString -> m (f [(ByteString, ByteString)])
+ Database.Redis.Sentinel: configResetstat :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: configRewrite :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: configSet :: RedisCtx m f => ByteString -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: connect :: SentinelConnectInfo -> IO SentinelConnection
+ Database.Redis.Sentinel: currentChannels :: MonadIO m => PubSubController -> m [RedisChannel]
+ Database.Redis.Sentinel: currentPChannels :: MonadIO m => PubSubController -> m [RedisPChannel]
+ Database.Redis.Sentinel: cursor0 :: Cursor
+ Database.Redis.Sentinel: data Aggregate
+ Database.Redis.Sentinel: data Condition
+ Database.Redis.Sentinel: data ConnectError
+ Database.Redis.Sentinel: data ConnectInfo
+ Database.Redis.Sentinel: data ConnectTimeout
+ Database.Redis.Sentinel: data ConnectionLostException
+ Database.Redis.Sentinel: data Cursor
+ Database.Redis.Sentinel: data DebugMode
+ Database.Redis.Sentinel: data Message
+ Database.Redis.Sentinel: data MigrateOpts
+ Database.Redis.Sentinel: data PortID
+ Database.Redis.Sentinel: data PubSub
+ Database.Redis.Sentinel: data PubSubController
+ Database.Redis.Sentinel: data Queued a
+ Database.Redis.Sentinel: data RangeLex a
+ Database.Redis.Sentinel: data Redis a
+ Database.Redis.Sentinel: data RedisSentinelException
+ Database.Redis.Sentinel: data RedisTx a
+ Database.Redis.Sentinel: data RedisType
+ Database.Redis.Sentinel: data Reply
+ Database.Redis.Sentinel: data ReplyMode
+ Database.Redis.Sentinel: data ScanOpts
+ Database.Redis.Sentinel: data SentinelConnectInfo
+ Database.Redis.Sentinel: data SentinelConnection
+ Database.Redis.Sentinel: data SetOpts
+ Database.Redis.Sentinel: data Slowlog
+ Database.Redis.Sentinel: data SortOpts
+ Database.Redis.Sentinel: data SortOrder
+ Database.Redis.Sentinel: data Status
+ Database.Redis.Sentinel: data StreamsRecord
+ Database.Redis.Sentinel: data TrimOpts
+ Database.Redis.Sentinel: data TxResult a
+ Database.Redis.Sentinel: data XClaimOpts
+ Database.Redis.Sentinel: data XInfoConsumersResponse
+ Database.Redis.Sentinel: data XInfoGroupsResponse
+ Database.Redis.Sentinel: data XInfoStreamResponse
+ Database.Redis.Sentinel: data XPendingDetailRecord
+ Database.Redis.Sentinel: data XPendingSummaryResponse
+ Database.Redis.Sentinel: data XReadOpts
+ Database.Redis.Sentinel: data XReadResponse
+ Database.Redis.Sentinel: data ZaddOpts
+ Database.Redis.Sentinel: dbsize :: RedisCtx m f => m (f Integer)
+ Database.Redis.Sentinel: debugObject :: RedisCtx m f => ByteString -> m (f ByteString)
+ Database.Redis.Sentinel: decode :: RedisResult a => Reply -> Either Reply a
+ Database.Redis.Sentinel: decr :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: decrby :: RedisCtx m f => ByteString -> Integer -> m (f Integer)
+ Database.Redis.Sentinel: defaultConnectInfo :: ConnectInfo
+ Database.Redis.Sentinel: defaultMigrateOpts :: MigrateOpts
+ Database.Redis.Sentinel: defaultScanOpts :: ScanOpts
+ Database.Redis.Sentinel: defaultSortOpts :: SortOpts
+ Database.Redis.Sentinel: defaultXClaimOpts :: XClaimOpts
+ Database.Redis.Sentinel: defaultXreadOpts :: XReadOpts
+ Database.Redis.Sentinel: defaultZaddOpts :: ZaddOpts
+ Database.Redis.Sentinel: del :: RedisCtx m f => [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: disconnect :: Connection -> IO ()
+ Database.Redis.Sentinel: dump :: RedisCtx m f => ByteString -> m (f ByteString)
+ Database.Redis.Sentinel: echo :: RedisCtx m f => ByteString -> m (f ByteString)
+ Database.Redis.Sentinel: eval :: (RedisCtx m f, RedisResult a) => ByteString -> [ByteString] -> [ByteString] -> m (f a)
+ Database.Redis.Sentinel: evalsha :: (RedisCtx m f, RedisResult a) => ByteString -> [ByteString] -> [ByteString] -> m (f a)
+ Database.Redis.Sentinel: exists :: RedisCtx m f => ByteString -> m (f Bool)
+ Database.Redis.Sentinel: expire :: RedisCtx m f => ByteString -> Integer -> m (f Bool)
+ Database.Redis.Sentinel: expireat :: RedisCtx m f => ByteString -> Integer -> m (f Bool)
+ Database.Redis.Sentinel: flushall :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: flushdb :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: get :: RedisCtx m f => ByteString -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: getType :: RedisCtx m f => ByteString -> m (f RedisType)
+ Database.Redis.Sentinel: getbit :: RedisCtx m f => ByteString -> Integer -> m (f Integer)
+ Database.Redis.Sentinel: getrange :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f ByteString)
+ Database.Redis.Sentinel: getset :: RedisCtx m f => ByteString -> ByteString -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: hdel :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: hexists :: RedisCtx m f => ByteString -> ByteString -> m (f Bool)
+ Database.Redis.Sentinel: hget :: RedisCtx m f => ByteString -> ByteString -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: hgetall :: RedisCtx m f => ByteString -> m (f [(ByteString, ByteString)])
+ Database.Redis.Sentinel: hincrby :: RedisCtx m f => ByteString -> ByteString -> Integer -> m (f Integer)
+ Database.Redis.Sentinel: hincrbyfloat :: RedisCtx m f => ByteString -> ByteString -> Double -> m (f Double)
+ Database.Redis.Sentinel: hkeys :: RedisCtx m f => ByteString -> m (f [ByteString])
+ Database.Redis.Sentinel: hlen :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: hmget :: RedisCtx m f => ByteString -> [ByteString] -> m (f [Maybe ByteString])
+ Database.Redis.Sentinel: hmset :: RedisCtx m f => ByteString -> [(ByteString, ByteString)] -> m (f Status)
+ Database.Redis.Sentinel: hscan :: RedisCtx m f => ByteString -> Cursor -> m (f (Cursor, [(ByteString, ByteString)]))
+ Database.Redis.Sentinel: hscanOpts :: RedisCtx m f => ByteString -> Cursor -> ScanOpts -> m (f (Cursor, [(ByteString, ByteString)]))
+ Database.Redis.Sentinel: hset :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Bool)
+ Database.Redis.Sentinel: hsetnx :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Bool)
+ Database.Redis.Sentinel: hstrlen :: RedisCtx m f => ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: hvals :: RedisCtx m f => ByteString -> m (f [ByteString])
+ Database.Redis.Sentinel: incr :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: incrby :: RedisCtx m f => ByteString -> Integer -> m (f Integer)
+ Database.Redis.Sentinel: incrbyfloat :: RedisCtx m f => ByteString -> Double -> m (f Double)
+ Database.Redis.Sentinel: inf :: RealFloat a => a
+ Database.Redis.Sentinel: info :: RedisCtx m f => m (f ByteString)
+ Database.Redis.Sentinel: infoSection :: RedisCtx m f => ByteString -> m (f ByteString)
+ Database.Redis.Sentinel: instance GHC.Exception.Type.Exception Database.Redis.Sentinel.RedisSentinelException
+ Database.Redis.Sentinel: instance GHC.Show.Show Database.Redis.Sentinel.RedisSentinelException
+ Database.Redis.Sentinel: instance GHC.Show.Show Database.Redis.Sentinel.SentinelConnectInfo
+ Database.Redis.Sentinel: keys :: RedisCtx m f => ByteString -> m (f [ByteString])
+ Database.Redis.Sentinel: lastsave :: RedisCtx m f => m (f Integer)
+ Database.Redis.Sentinel: liftRedis :: MonadRedis m => Redis a -> m a
+ Database.Redis.Sentinel: lindex :: RedisCtx m f => ByteString -> Integer -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: linsertAfter :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: linsertBefore :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: llen :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: lpop :: RedisCtx m f => ByteString -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: lpush :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: lpushx :: RedisCtx m f => ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: lrange :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f [ByteString])
+ Database.Redis.Sentinel: lrem :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: lset :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: ltrim :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f Status)
+ Database.Redis.Sentinel: mget :: RedisCtx m f => [ByteString] -> m (f [Maybe ByteString])
+ Database.Redis.Sentinel: migrate :: RedisCtx m f => ByteString -> ByteString -> ByteString -> Integer -> Integer -> m (f Status)
+ Database.Redis.Sentinel: migrateMultiple :: RedisCtx m f => ByteString -> ByteString -> Integer -> Integer -> MigrateOpts -> [ByteString] -> m (f Status)
+ Database.Redis.Sentinel: move :: RedisCtx m f => ByteString -> Integer -> m (f Bool)
+ Database.Redis.Sentinel: mset :: RedisCtx m f => [(ByteString, ByteString)] -> m (f Status)
+ Database.Redis.Sentinel: msetnx :: RedisCtx m f => [(ByteString, ByteString)] -> m (f Bool)
+ Database.Redis.Sentinel: multiExec :: RedisTx (Queued a) -> Redis (TxResult a)
+ Database.Redis.Sentinel: newPubSubController :: MonadIO m => [(RedisChannel, MessageCallback)] -> [(RedisPChannel, PMessageCallback)] -> m PubSubController
+ Database.Redis.Sentinel: objectEncoding :: RedisCtx m f => ByteString -> m (f ByteString)
+ Database.Redis.Sentinel: objectIdletime :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: objectRefcount :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: parseConnectInfo :: String -> Either String ConnectInfo
+ Database.Redis.Sentinel: persist :: RedisCtx m f => ByteString -> m (f Bool)
+ Database.Redis.Sentinel: pexpire :: RedisCtx m f => ByteString -> Integer -> m (f Bool)
+ Database.Redis.Sentinel: pexpireat :: RedisCtx m f => ByteString -> Integer -> m (f Bool)
+ Database.Redis.Sentinel: pfadd :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: pfcount :: RedisCtx m f => [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: pfmerge :: RedisCtx m f => ByteString -> [ByteString] -> m (f ByteString)
+ Database.Redis.Sentinel: ping :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: psetex :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: psubscribe :: [ByteString] -> PubSub
+ Database.Redis.Sentinel: pttl :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: pubSub :: PubSub -> (Message -> IO PubSub) -> Redis ()
+ Database.Redis.Sentinel: pubSubForever :: Connection -> PubSubController -> IO () -> IO ()
+ Database.Redis.Sentinel: publish :: RedisCtx m f => ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: punsubscribe :: [ByteString] -> PubSub
+ Database.Redis.Sentinel: quit :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: randomkey :: RedisCtx m f => m (f (Maybe ByteString))
+ Database.Redis.Sentinel: reRedis :: ReaderT RedisEnv IO a -> Redis a
+ Database.Redis.Sentinel: removeChannels :: MonadIO m => PubSubController -> [RedisChannel] -> [RedisPChannel] -> m ()
+ Database.Redis.Sentinel: removeChannelsAndWait :: MonadIO m => PubSubController -> [RedisChannel] -> [RedisPChannel] -> m ()
+ Database.Redis.Sentinel: rename :: RedisCtx m f => ByteString -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: renamenx :: RedisCtx m f => ByteString -> ByteString -> m (f Bool)
+ Database.Redis.Sentinel: restore :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: restoreReplace :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: returnDecode :: (RedisCtx m f, RedisResult a) => Reply -> m (f a)
+ Database.Redis.Sentinel: rpop :: RedisCtx m f => ByteString -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: rpoplpush :: RedisCtx m f => ByteString -> ByteString -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: rpush :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: rpushx :: RedisCtx m f => ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: runRedis :: SentinelConnection -> Redis (Either Reply a) -> IO (Either Reply a)
+ Database.Redis.Sentinel: sadd :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: save :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: scan :: RedisCtx m f => Cursor -> m (f (Cursor, [ByteString]))
+ Database.Redis.Sentinel: scanOpts :: RedisCtx m f => Cursor -> ScanOpts -> m (f (Cursor, [ByteString]))
+ Database.Redis.Sentinel: scard :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: scriptDebug :: RedisCtx m f => DebugMode -> m (f Bool)
+ Database.Redis.Sentinel: scriptExists :: RedisCtx m f => [ByteString] -> m (f [Bool])
+ Database.Redis.Sentinel: scriptFlush :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: scriptKill :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: scriptLoad :: RedisCtx m f => ByteString -> m (f ByteString)
+ Database.Redis.Sentinel: sdiff :: RedisCtx m f => [ByteString] -> m (f [ByteString])
+ Database.Redis.Sentinel: sdiffstore :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: select :: RedisCtx m f => Integer -> m (f Status)
+ Database.Redis.Sentinel: sendRequest :: (RedisCtx m f, RedisResult a) => [ByteString] -> m (f a)
+ Database.Redis.Sentinel: set :: RedisCtx m f => ByteString -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: setOpts :: RedisCtx m f => ByteString -> ByteString -> SetOpts -> m (f Status)
+ Database.Redis.Sentinel: setbit :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: setex :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: setnx :: RedisCtx m f => ByteString -> ByteString -> m (f Bool)
+ Database.Redis.Sentinel: setrange :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: sinter :: RedisCtx m f => [ByteString] -> m (f [ByteString])
+ Database.Redis.Sentinel: sinterstore :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: sismember :: RedisCtx m f => ByteString -> ByteString -> m (f Bool)
+ Database.Redis.Sentinel: slaveof :: RedisCtx m f => ByteString -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: slowlogGet :: RedisCtx m f => Integer -> m (f [Slowlog])
+ Database.Redis.Sentinel: slowlogLen :: RedisCtx m f => m (f Integer)
+ Database.Redis.Sentinel: slowlogReset :: RedisCtx m f => m (f Status)
+ Database.Redis.Sentinel: smembers :: RedisCtx m f => ByteString -> m (f [ByteString])
+ Database.Redis.Sentinel: smove :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Bool)
+ Database.Redis.Sentinel: sort :: RedisCtx m f => ByteString -> SortOpts -> m (f [ByteString])
+ Database.Redis.Sentinel: sortStore :: RedisCtx m f => ByteString -> ByteString -> SortOpts -> m (f Integer)
+ Database.Redis.Sentinel: spop :: RedisCtx m f => ByteString -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: spopN :: RedisCtx m f => ByteString -> Integer -> m (f [ByteString])
+ Database.Redis.Sentinel: srandmember :: RedisCtx m f => ByteString -> m (f (Maybe ByteString))
+ Database.Redis.Sentinel: srandmemberN :: RedisCtx m f => ByteString -> Integer -> m (f [ByteString])
+ Database.Redis.Sentinel: srem :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: sscan :: RedisCtx m f => ByteString -> Cursor -> m (f (Cursor, [ByteString]))
+ Database.Redis.Sentinel: sscanOpts :: RedisCtx m f => ByteString -> Cursor -> ScanOpts -> m (f (Cursor, [ByteString]))
+ Database.Redis.Sentinel: strlen :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: subscribe :: [ByteString] -> PubSub
+ Database.Redis.Sentinel: sunion :: RedisCtx m f => [ByteString] -> m (f [ByteString])
+ Database.Redis.Sentinel: sunionstore :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: time :: RedisCtx m f => m (f (Integer, Integer))
+ Database.Redis.Sentinel: ttl :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: type MessageCallback = ByteString -> IO ()
+ Database.Redis.Sentinel: type PMessageCallback = RedisChannel -> ByteString -> IO ()
+ Database.Redis.Sentinel: type RedisChannel = ByteString
+ Database.Redis.Sentinel: type RedisPChannel = ByteString
+ Database.Redis.Sentinel: type UnregisterCallbacksAction = IO ()
+ Database.Redis.Sentinel: unRedis :: Redis a -> ReaderT RedisEnv IO a
+ Database.Redis.Sentinel: unsubscribe :: [ByteString] -> PubSub
+ Database.Redis.Sentinel: unwatch :: Redis (Either Reply Status)
+ Database.Redis.Sentinel: wait :: RedisCtx m f => Integer -> Integer -> m (f Integer)
+ Database.Redis.Sentinel: watch :: [ByteString] -> Redis (Either Reply Status)
+ Database.Redis.Sentinel: withCheckedConnect :: (MonadMask m, MonadIO m) => ConnectInfo -> (Connection -> m c) -> m c
+ Database.Redis.Sentinel: withConnect :: (MonadMask m, MonadIO m) => ConnectInfo -> (Connection -> m c) -> m c
+ Database.Redis.Sentinel: xack :: RedisCtx m f => ByteString -> ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: xadd :: RedisCtx m f => ByteString -> ByteString -> [(ByteString, ByteString)] -> m (f ByteString)
+ Database.Redis.Sentinel: xaddOpts :: RedisCtx m f => ByteString -> ByteString -> [(ByteString, ByteString)] -> TrimOpts -> m (f ByteString)
+ Database.Redis.Sentinel: xclaim :: RedisCtx m f => ByteString -> ByteString -> ByteString -> Integer -> XClaimOpts -> [ByteString] -> m (f [StreamsRecord])
+ Database.Redis.Sentinel: xclaimJustIds :: RedisCtx m f => ByteString -> ByteString -> ByteString -> Integer -> XClaimOpts -> [ByteString] -> m (f [ByteString])
+ Database.Redis.Sentinel: xdel :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: xgroupCreate :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: xgroupDelConsumer :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: xgroupDestroy :: RedisCtx m f => ByteString -> ByteString -> m (f Bool)
+ Database.Redis.Sentinel: xgroupSetId :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Status)
+ Database.Redis.Sentinel: xinfoConsumers :: RedisCtx m f => ByteString -> ByteString -> m (f [XInfoConsumersResponse])
+ Database.Redis.Sentinel: xinfoGroups :: RedisCtx m f => ByteString -> m (f [XInfoGroupsResponse])
+ Database.Redis.Sentinel: xinfoStream :: RedisCtx m f => ByteString -> m (f XInfoStreamResponse)
+ Database.Redis.Sentinel: xlen :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: xpendingDetail :: RedisCtx m f => ByteString -> ByteString -> ByteString -> ByteString -> Integer -> Maybe ByteString -> m (f [XPendingDetailRecord])
+ Database.Redis.Sentinel: xpendingSummary :: RedisCtx m f => ByteString -> ByteString -> Maybe ByteString -> m (f XPendingSummaryResponse)
+ Database.Redis.Sentinel: xrange :: RedisCtx m f => ByteString -> ByteString -> ByteString -> Maybe Integer -> m (f [StreamsRecord])
+ Database.Redis.Sentinel: xread :: RedisCtx m f => [(ByteString, ByteString)] -> m (f (Maybe [XReadResponse]))
+ Database.Redis.Sentinel: xreadGroup :: RedisCtx m f => ByteString -> ByteString -> [(ByteString, ByteString)] -> m (f (Maybe [XReadResponse]))
+ Database.Redis.Sentinel: xreadGroupOpts :: RedisCtx m f => ByteString -> ByteString -> [(ByteString, ByteString)] -> XReadOpts -> m (f (Maybe [XReadResponse]))
+ Database.Redis.Sentinel: xreadOpts :: RedisCtx m f => [(ByteString, ByteString)] -> XReadOpts -> m (f (Maybe [XReadResponse]))
+ Database.Redis.Sentinel: xrevRange :: RedisCtx m f => ByteString -> ByteString -> ByteString -> Maybe Integer -> m (f [StreamsRecord])
+ Database.Redis.Sentinel: xtrim :: RedisCtx m f => ByteString -> TrimOpts -> m (f Integer)
+ Database.Redis.Sentinel: zadd :: RedisCtx m f => ByteString -> [(Double, ByteString)] -> m (f Integer)
+ Database.Redis.Sentinel: zaddOpts :: RedisCtx m f => ByteString -> [(Double, ByteString)] -> ZaddOpts -> m (f Integer)
+ Database.Redis.Sentinel: zcard :: RedisCtx m f => ByteString -> m (f Integer)
+ Database.Redis.Sentinel: zcount :: RedisCtx m f => ByteString -> Double -> Double -> m (f Integer)
+ Database.Redis.Sentinel: zincrby :: RedisCtx m f => ByteString -> Integer -> ByteString -> m (f Double)
+ Database.Redis.Sentinel: zinterstore :: RedisCtx m f => ByteString -> [ByteString] -> Aggregate -> m (f Integer)
+ Database.Redis.Sentinel: zinterstoreWeights :: RedisCtx m f => ByteString -> [(ByteString, Double)] -> Aggregate -> m (f Integer)
+ Database.Redis.Sentinel: zlexcount :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: zrange :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f [ByteString])
+ Database.Redis.Sentinel: zrangeWithscores :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f [(ByteString, Double)])
+ Database.Redis.Sentinel: zrangebylex :: RedisCtx m f => ByteString -> RangeLex ByteString -> RangeLex ByteString -> m (f [ByteString])
+ Database.Redis.Sentinel: zrangebylexLimit :: RedisCtx m f => ByteString -> RangeLex ByteString -> RangeLex ByteString -> Integer -> Integer -> m (f [ByteString])
+ Database.Redis.Sentinel: zrangebyscore :: RedisCtx m f => ByteString -> Double -> Double -> m (f [ByteString])
+ Database.Redis.Sentinel: zrangebyscoreLimit :: RedisCtx m f => ByteString -> Double -> Double -> Integer -> Integer -> m (f [ByteString])
+ Database.Redis.Sentinel: zrangebyscoreWithscores :: RedisCtx m f => ByteString -> Double -> Double -> m (f [(ByteString, Double)])
+ Database.Redis.Sentinel: zrangebyscoreWithscoresLimit :: RedisCtx m f => ByteString -> Double -> Double -> Integer -> Integer -> m (f [(ByteString, Double)])
+ Database.Redis.Sentinel: zrank :: RedisCtx m f => ByteString -> ByteString -> m (f (Maybe Integer))
+ Database.Redis.Sentinel: zrem :: RedisCtx m f => ByteString -> [ByteString] -> m (f Integer)
+ Database.Redis.Sentinel: zremrangebylex :: RedisCtx m f => ByteString -> ByteString -> ByteString -> m (f Integer)
+ Database.Redis.Sentinel: zremrangebyrank :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f Integer)
+ Database.Redis.Sentinel: zremrangebyscore :: RedisCtx m f => ByteString -> Double -> Double -> m (f Integer)
+ Database.Redis.Sentinel: zrevrange :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f [ByteString])
+ Database.Redis.Sentinel: zrevrangeWithscores :: RedisCtx m f => ByteString -> Integer -> Integer -> m (f [(ByteString, Double)])
+ Database.Redis.Sentinel: zrevrangebyscore :: RedisCtx m f => ByteString -> Double -> Double -> m (f [ByteString])
+ Database.Redis.Sentinel: zrevrangebyscoreLimit :: RedisCtx m f => ByteString -> Double -> Double -> Integer -> Integer -> m (f [ByteString])
+ Database.Redis.Sentinel: zrevrangebyscoreWithscores :: RedisCtx m f => ByteString -> Double -> Double -> m (f [(ByteString, Double)])
+ Database.Redis.Sentinel: zrevrangebyscoreWithscoresLimit :: RedisCtx m f => ByteString -> Double -> Double -> Integer -> Integer -> m (f [(ByteString, Double)])
+ Database.Redis.Sentinel: zrevrank :: RedisCtx m f => ByteString -> ByteString -> m (f (Maybe Integer))
+ Database.Redis.Sentinel: zscan :: RedisCtx m f => ByteString -> Cursor -> m (f (Cursor, [(ByteString, Double)]))
+ Database.Redis.Sentinel: zscanOpts :: RedisCtx m f => ByteString -> Cursor -> ScanOpts -> m (f (Cursor, [(ByteString, Double)]))
+ Database.Redis.Sentinel: zscore :: RedisCtx m f => ByteString -> ByteString -> m (f (Maybe Double))
+ Database.Redis.Sentinel: zunionstore :: RedisCtx m f => ByteString -> [ByteString] -> Aggregate -> m (f Integer)
+ Database.Redis.Sentinel: zunionstoreWeights :: RedisCtx m f => ByteString -> [(ByteString, Double)] -> Aggregate -> m (f Integer)

Files

CHANGELOG view
@@ -1,5 +1,9 @@ # Changelog for Hedis +## 0.12.15++* PR #154. Implement Redis Sentinel support+ ## 0.12.14  * PR #153. Publicly expose ConnectTimeout exception
hedis.cabal view
@@ -1,5 +1,5 @@ name:               hedis-version:            0.12.14+version:            0.12.15 synopsis:     Client library for the Redis datastore: supports full command set,     pipelining.@@ -68,6 +68,7 @@   if flag(dev)     ghc-prof-options: -auto-all   exposed-modules:  Database.Redis+                  , Database.Redis.Sentinel                   , Database.Redis.Core.Internal   build-depends:    scanner >= 0.2,                     async >= 2.1,
+ src/Database/Redis/Sentinel.hs view
@@ -0,0 +1,218 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE NamedFieldPuns    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE StrictData        #-}+{-# LANGUAGE TypeApplications  #-}++-- | "Database.Redis" like interface with connection through Redis Sentinel.+--+-- More details here: <https://redis.io/topics/sentinel>.+--+-- Example:+--+-- @+-- conn <- 'connect' 'SentinelConnectionInfo' (("localhost", PortNumber 26379) :| []) "mymaster" 'defaultConnectInfo'+--+-- 'runRedis' conn $ do+--   'set' "hello" "world"+-- @+--+-- When connection is opened, the Sentinels will be queried to get current master. Subsequent 'runRedis'+-- calls will talk to that master.+--+-- If 'runRedis' call fails, the next call will choose a new master to talk to.+--+-- This implementation is based on Gist by Emanuel Borsboom+-- at <https://gist.github.com/borsboom/681d37d273d5c4168723>+module Database.Redis.Sentinel+  (+    -- * Connection+    SentinelConnectInfo(..)+  , SentinelConnection+  , connect+    -- * runRedis with Sentinel support+  , runRedis+  , RedisSentinelException(..)++    -- * Re-export Database.Redis+  , module Database.Redis+  ) where++import           Control.Concurrent+import           Control.Exception     (Exception, IOException, evaluate, throwIO)+import           Control.Monad+import           Control.Monad.Catch   (Handler (..), MonadCatch, catches, throwM)+import           Control.Monad.Except+import           Data.ByteString       (ByteString)+import qualified Data.ByteString       as BS+import qualified Data.ByteString.Char8 as BS8+import           Data.Foldable         (toList)+import           Data.List             (delete)+import           Data.List.NonEmpty    (NonEmpty (..))+import           Data.Typeable         (Typeable)+import           Data.Unique+import           Network.Socket        (HostName)++import           Database.Redis hiding (Connection, connect, runRedis)+import qualified Database.Redis as Redis++-- | Interact with a Redis datastore.  See 'Database.Redis.runRedis' for details.+runRedis :: SentinelConnection+         -> Redis (Either Reply a)+         -> IO (Either Reply a)+runRedis (SentinelConnection connMVar) action = do+  (baseConn, preToken) <- modifyMVar connMVar $ \oldConnection@SentinelConnection'+          { rcCheckFailover+          , rcToken = oldToken+          , rcSentinelConnectInfo = oldConnectInfo+          , rcMasterConnectInfo = oldMasterConnectInfo+          , rcBaseConnection = oldBaseConnection } ->+      if rcCheckFailover+        then do+          (newConnectInfo, newMasterConnectInfo) <- updateMaster oldConnectInfo+          newToken <- newUnique+          (connInfo, conn) <-+            if sameHost newMasterConnectInfo oldMasterConnectInfo+              then return (oldMasterConnectInfo, oldBaseConnection)+              else do+                newConn <- Redis.connect newMasterConnectInfo+                return (newMasterConnectInfo, newConn)++          return+            ( SentinelConnection'+              { rcCheckFailover = False+              , rcToken = newToken+              , rcSentinelConnectInfo = newConnectInfo+              , rcMasterConnectInfo = connInfo+              , rcBaseConnection = conn+              }+            , (conn, newToken)+            )+        else return (oldConnection, (oldBaseConnection, oldToken))++  -- Use evaluate to make sure we catch exceptions from 'runRedis'.+  reply <- (Redis.runRedis baseConn action >>= evaluate)+    `catchRedisRethrow` (\_ -> setCheckSentinel preToken)+  case reply of+    Left (Error e) | "READONLY " `BS.isPrefixOf` e ->+        -- This means our connection has turned into a slave+        setCheckSentinel preToken+    _ -> return ()+  return reply++  where+    sameHost :: Redis.ConnectInfo -> Redis.ConnectInfo -> Bool+    sameHost l r = connectHost l == connectHost r && connectPort l == connectPort r++    setCheckSentinel preToken = modifyMVar_ connMVar $ \conn@SentinelConnection'{rcToken} ->+      if preToken == rcToken+        then do+          newToken <- newUnique+          return (conn{rcToken = newToken, rcCheckFailover = True})+        else return conn+++connect :: SentinelConnectInfo -> IO SentinelConnection+connect origConnectInfo = do+  (connectInfo, masterConnectInfo) <- updateMaster origConnectInfo+  conn <- Redis.connect masterConnectInfo+  token <- newUnique++  SentinelConnection <$> newMVar SentinelConnection'+    { rcCheckFailover = False+    , rcToken = token+    , rcSentinelConnectInfo = connectInfo+    , rcMasterConnectInfo = masterConnectInfo+    , rcBaseConnection = conn+    }++updateMaster :: SentinelConnectInfo+             -> IO (SentinelConnectInfo, Redis.ConnectInfo)+updateMaster sci@SentinelConnectInfo{..} = do+    -- This is using the Either monad "backwards" -- Left means stop because we've made a connection,+    -- Right means try again.+    resultEither <- runExceptT $ forM_ connectSentinels $ \(host, port) -> do+      trySentinel host port `catchRedis` (\_ -> return ())+++    case resultEither of+        Left (conn, sentinelPair) -> return+          ( sci+            { connectSentinels = sentinelPair :| delete sentinelPair (toList connectSentinels)+            }+          , conn+          )+        Right () -> throwIO $ NoSentinels connectSentinels+  where+    trySentinel :: HostName -> PortID -> ExceptT (Redis.ConnectInfo, (HostName, PortID)) IO ()+    trySentinel sentinelHost sentinelPort = do+      -- bang to ensure exceptions from runRedis get thrown immediately.+      !replyE <- liftIO $ do+        !sentinelConn <- Redis.connect $ Redis.defaultConnectInfo+            { connectHost = sentinelHost+            , connectPort = sentinelPort+            , connectMaxConnections = 1+            }+        Redis.runRedis sentinelConn $ sendRequest+          ["SENTINEL", "get-master-addr-by-name", connectMasterName]++      case replyE of+        Right [host, port] ->+          throwError+            ( connectBaseInfo+              { connectHost = BS8.unpack host+              , connectPort =+                  maybe+                    (PortNumber 26379)+                    (PortNumber . fromIntegral . fst)+                    $ BS8.readInt port+              }+            , (sentinelHost, sentinelPort)+            )+        _ -> return ()++catchRedisRethrow :: MonadCatch m => m a -> (String -> m ()) -> m a+catchRedisRethrow action handler =+  action `catches`+    [ Handler $ \ex -> handler (show @IOException ex) >> throwM ex+    , Handler $ \ex -> handler (show @ConnectionLostException ex) >> throwM ex+    ]++catchRedis :: MonadCatch m => m a -> (String -> m a) -> m a+catchRedis action handler =+  action `catches`+    [ Handler $ \ex -> handler (show @IOException ex)+    , Handler $ \ex -> handler (show @ConnectionLostException ex)+    ]++newtype SentinelConnection = SentinelConnection (MVar SentinelConnection')++data SentinelConnection'+  = SentinelConnection'+      { rcCheckFailover       :: Bool+      , rcToken               :: Unique+      , rcSentinelConnectInfo :: SentinelConnectInfo+      , rcMasterConnectInfo   :: Redis.ConnectInfo+      , rcBaseConnection      :: Redis.Connection+      }++-- | Configuration of Sentinel hosts.+data SentinelConnectInfo+  = SentinelConnectInfo+      { connectSentinels  :: NonEmpty (HostName, PortID)+        -- ^ List of sentinels.+      , connectMasterName :: ByteString+        -- ^ Name of master to connect to.+      , connectBaseInfo   :: Redis.ConnectInfo+        -- ^ This is used to configure auth and other parameters for Redis connection,+        -- but 'Redis.connectHost' and 'Redis.connectPort' are ignored.+      }+  deriving (Show)++-- | Exception thrown by "Database.Redis.Sentinel".+data RedisSentinelException+  = NoSentinels (NonEmpty (HostName, PortID))+    -- ^ Thrown if no sentinel can be reached.+  deriving (Show, Typeable, Exception)