!G      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ None7hedis:Low-level representation of replies from the Redis server.None"#2_,M hedisConnection socket-handle.hedis!Reply thunks for unsent requests.hedisKReply thunks for requests "in the pipeline". Refers to the same list as , but can have an offset.hedisDNumber of pending replies and thus the difference length between  and <. length connPending - pendingCount = length connReplieshedisOWrite the request to the socket output buffer, without actually sending. The  is !ed when reading replies from the .hedis3Take a reply-thunk from the list of future replies.hedis6Flush the socket. Normally, the socket is flushed in  (actually  conGetReplies{), but for the multithreaded pub/sub code, the sending thread needs to explicitly flush the subscription change requests.hedis2Send a request and receive the corresponding replyhedisA list of all future  s of the .CThe spine of the list can be evaluated without forcing the replies.Evaluating/forcing a  from the list will $ the reading and parsing from the n. To ensure correct ordering, each Reply first evaluates (and thus reads from the network) the previous one.F only evaluates it's result once, making this function thread-safe. @ as implemented by GHC is also threadsafe, it is safe to call 8 here. The list constructor '(:)' must be called from within: unsafeInterleaveIO, to keep the replies in correct order. None1M0khedisEContext for normal command execution, outside of transactions. Use runRedis to run actions of this type..In this context, each result is wrapped in an 8 to account for the possibility of Redis returning an  reply.    None7=?0 !"None "#12=?@ACMg*&hedis.Information for connnecting to a Redis server.!It is recommended to not use the ') data constructor directly. Instead use 9 and update it with record syntax. For example to connect to a password protected Redis server running on localhost and listening to the default port: ^myConnectInfo :: ConnectInfo myConnectInfo = defaultConnectInfo {connectAuth = Just "secret"} *hedis0When the server is protected by a password, set * to @ the password. Each connection will then authenticate by the ? command.+hedisEach connection will @# the database with the given index.,hedisRMaximum number of connections to keep open. The smallest acceptable value is 1.-hedistAmount of time for which an unused connection is kept open. The smallest acceptable value is 0.5 seconds. If the timeoutK value in your redis.conf file is non-zero, it should be larger than -..hedis@Optional timeout until connection to Redis gets established. ConnectTimeoutExceptionD gets thrown if no socket get connected in this interval of time./hedisAOptional TLS parameters. TLS will be enabled if this is provided.0hedisFA threadsafe pool of network connections to a Redis server. Use the : function to create one.3hedis:This class captures the following behaviour: In a context mF, a command will return its result wrapped in a "container" of type f.XPlease refer to the Command Type Signatures section of this page for more information.5hedis7Interact with a Redis datastore specified by the given 0. Each call of 5% takes a network connection from the 0 pool and runs the given  action. Calls to 5A may thus block while all connections from the pool are in use.6hedisDeconstruct Redis constructor.6 and 7= can be used to define instances for arbitrary typeclasses.~WARNING! These functions are considered internal and no guarantee is given at this point that they will not break in future.7hedisReconstruct Redis constructor.hedisInternal version of 5 that does not depend on the 0= abstraction. Used to run the AUTH command when connecting.8hedis8 can be used to implement commands from experimental versions of Redis. An example of how to implement a command is given below. <-- |Redis DEBUG OBJECT command debugObject :: ByteString ->  (Either  ByteString) debugObject key = 8 ["DEBUG", "OBJECT", key] 9hedis#Default information for connecting:  connectHost = "localhost" connectPort = PortNumber 6379 -- Redis default port connectAuth = Nothing -- No password connectDatabase = 0 -- SELECT database 0 connectMaxConnections = 50 -- Up to 50 connections connectMaxIdleTime = 30 -- Keep open for 30 seconds connectTimeout = Nothing -- Don't add timeout logic connectTLSParams = Nothing -- Do not use TLS :hedis Constructs a 03 pool to a Redis server designated by the given &X. The first connection is not actually established until the first call to the server.;hedis Constructs a 02 pool to a Redis server designated by the given &, then tests if the server is actually there. Throws an exception if the connection to the Redis server can't be established.<hedis'Destroy all idle resources in the pool.=hedisMemory bracket around : and <. >hedisMemory bracket around ; and <?hedispassword@hedisindex##$%&'()*+,-./0123456789:;<=>?@ANone7=?@AM Bhedis Result of a J transaction.ChedisLTransaction completed successfully. The wrapped value corresponds to the F value returned from the J argument action.Dhedis&Transaction aborted due to an earlier H command.Ehedis)At least one of the commands returned an  reply.FhedisA F_ value represents the result of a command inside a transaction. It is a proxy object for the actual? result, which will only be available after returning from a J transaction.F( values are composable by utilizing the ,  or  interfaces.Ghedis7Command-context inside of MULTI/EXEC transactions. Use J to run actions of this type.In the G context, all commands return a F' value. It is a proxy object for the actualH result, which will only be available after finishing the transaction.HhedisGWatch the given keys to determine execution of the MULTI/EXEC block ( http://redis.io/commands/watch).IhedisForget about all watched keys ( http://redis.io/commands/unwatch).JhedisaRun commands inside a transaction. For documentation on the semantics of Redis transaction see  #http://redis.io/topics/transactions.SInside the transaction block, command functions return their result wrapped in a F. The F` result is a proxy object for the actual command's result, which will only be available after EXECing the transaction.Example usage (note how F 's ; instance is used to combine the two individual results): Y runRedis conn $ do set "hello" "hello" set "world" "world" helloworld <- J $ do hello <- get "hello" world <- get "world" return $ (,) <$> hello <*> world liftIO (print helloworld) Hhediskey BCDEFGHIJNone "#=>?GM&Khedis[A controller that stores a set of channels, pattern channels, and callbacks. It allows you to manage Pub/Sub subscriptions and pattern subscriptions and alter them at any time throughout the life of your program. You should typically create the controller at the start of your program and then store it through the life of your program, using a and c& to update the current subscriptions.LhedisQAn action that when executed will unregister the callbacks. It is returned from a or b# and typically you would use it in bracket to guarantee that you unsubscribe from channels. For example, if you are using websockets to distribute messages to clients, you could use something such as: websocketConn <- Network.WebSockets.acceptRequest pending let mycallback msg = Network.WebSockets.sendTextData websocketConn msg bracket (addChannelsAndWait ctrl [("hello", mycallback)] []) id $ const $ do {- loop here calling Network.WebSockets.receiveData -}MhedisA handler for a message from a psubscribed channel. The callback is passed the channel the message was sent on plus the message content. Similar to NM, callbacks are executed synchronously and any exceptions are rethrown from e.Nhedis_A handler for a message from a subscribed channel. The callback is passed the message content.Messages are processed synchronously in the receiving thread, so if the callback takes a long time it will block other callbacks and other messages from being received. If you need to move long-running work to a different thread, we suggest you use v with a reasonable bound, so that if messages are arriving faster than you can process them, you do eventually block.GIf the callback throws an exception, the exception will be thrown from eh which will cause the entire Redis connection for all subscriptions to be closed. As long as you call e in a loop you will reconnect to your subscribed channels, but you should probably add an exception handler to each callback to prevent this.OhedisA Redis pattern channel namePhedisA Redis channel nameWhedis'Encapsulates subscription changes. Use Y, Z, [, \ or 5 to construct a value. Combine values by using the  interface, i.e.  and .hedisWhile in PubSub mode, we keep track of the number of current subscriptions (as reported by Redis replies) and the number of messages we expect to receive after a SUBSCRIBE or PSUBSCRIBE command. We can safely leave the PubSub mode when both these numbers are zero.XhedisPost a message to a channel ( http://redis.io/commands/publish).Yhedis7Listen for messages published to the given channels ( "http://redis.io/commands/subscribe).Zhedis<Stop listening for messages posted to the given channels ( $http://redis.io/commands/unsubscribe).[hedisJListen for messages published to channels matching the given patterns ( #http://redis.io/commands/psubscribe).\hedisOStop listening for messages posted to channels matching the given patterns ( %http://redis.io/commands/punsubscribe).]hedisListens to published messages on subscribed channels and channels matching the subscribed patterns. For documentation on the semantics of Redis Pub/Sub see  http://redis.io/topics/pubsub.wThe given callback function is called for each received message. Subscription changes are triggered by the returned W=. To keep subscriptions unchanged, the callback can return .6Example: Subscribe to the "news" channel indefinitely. w pubSub (subscribe ["news"]) $ \msg -> do putStrLn $ "Message from " ++ show (msgChannel msg) return mempty :Example: Receive a single message from the "chat" channel.  pubSub (subscribe ["chat"]) $ \msg -> do putStrLn $ "Message from " ++ show (msgChannel msg) return $ unsubscribe ["chat"] RIt should be noted that Redis Pub/Sub by its nature is asynchronous so returning Z does not mean that callback won't be able to receive any further messages. And to guarantee that you won't won't process messages after unsubscription and won't unsubscribe from the same channel more than once you need to use IORef or something similar^hedis Create a new K{. Note that this does not subscribe to any channels, it just creates the controller. The subscriptions will happen once e is called._hedis(Get the list of current channels in the K. WARNING! This might not exactly reflect the subscribed channels in the Redis server, because there is a delay between adding or removing a channel in the KH and when Redis receives and processes the subscription change request.`hedis0Get the list of current pattern channels in the K. WARNING! This might not exactly reflect the subscribed channels in the Redis server, because there is a delay between adding or removing a channel in the KH and when Redis receives and processes the subscription change request.ahedisAdd channels into the K, and if there is an active e=, send the subscribe and psubscribe commands to Redis. The a function is thread-safe. This function does not wait for Redis to acknowledge that the channels have actually been subscribed; use b for that.MYou can subscribe to the same channel or pattern channel multiple times; the KP keeps a list of callbacks and executes each callback in response to a message.The return value is an action LH which will unregister the callbacks, which should typically used with bracket.bhedisCall aR and then wait for Redis to acknowledge that the channels are actually subscribed.hNote that this function waits for all pending subscription change requests, so if you for example call b from multiple threads simultaneously, they all will wait for all pending subscription changes to be acknowledged by Redis (this is due to the fact that we just track the total number of pending change requests sent to Redis and just wait until that count reaches zero).This also correctly waits if the network connection dies during the subscription change. Say that the network connection dies right after we send a subscription change to Redis. e will throw ConnectionLost and b) will continue to wait. Once you recall e with the same K, eQ will open a new connection, send subscription commands for all channels in the K (which include the ones we are waiting for), and wait for the responses from Redis. Only once we receive the response from Redis that it has subscribed to all channels in K will b unblock and return.chedisRemove channels from the K, and if there is an active e0, send the unsubscribe commands to Redis. Note that as soon as this function returns, no more callbacks will be executed even if more messages arrive during the period when we request to unsubscribe from the channel and Redis actually processes the unsubscribe request. This function is thread-safe..If you remove all channels, the connection in eJ to redis will stay open and waiting for any new channels from a call to a4. If you really want to close the connection, use   or   to kill the thread running e.hedisTInternal function to unsubscribe only from those channels matching the given handle.dhedisCall c and then wait for all pending subscription change requests to be acknowledged by Redis. This uses the same waiting logic as b . Since c immediately notifies the KU to start discarding messages, you likely don't need this function and can just use c.hedisInternal thread which listens for messages and executes callbacks. This is the only thread which ever receives data from the underlying connection.hedisInternal thread which sends subscription change requests. This is the only thread which ever sends data on the underlying connection.ehedisGOpen a connection to the Redis server, register to all channels in the K, and process messages and subscription change requests forever. The only way this will ever exit is if there is an exception from the network code or an unhandled exception in a N or M9. For example, if the network connection to Redis dies, e will throw a ConnectionLost5. When such an exception is thrown, you can recall e with the same K` which will open a new connection and resubscribe to all the channels which are tracked in the K.AThe general pattern is therefore during program startup create a K and fork a thread which calls e@ in a loop (using an exponential backoff algorithm such as the  )https://hackage.haskell.org/package/retryretryG package to not hammer the Redis server if it does die). For example, umyhandler :: ByteString -> IO () myhandler msg = putStrLn $ unpack $ decodeUtf8 msg onInitialComplete :: IO () onInitialComplete = putStrLn "Redis acknowledged that mychannel is now subscribed" main :: IO () main = do conn <- connect defaultConnectInfo pubSubCtrl <- newPubSubController [("mychannel", myhandler)] [] forkIO $ forever $ pubSubForever conn pubSubCtrl onInitialComplete `catch` (\(e :: SomeException) -> do putStrLn $ "Got error: " ++ show e threadDelay $ 50*1000) -- TODO: use exponential backoff {- elsewhere in your program, use pubSubCtrl to change subscriptions -} At most one active e! can be running against a single K' at any time. If two active calls to e share a single K there will be deadlocks. If you do want to process messages using multiple connections to Redis, you can create more than one K5. For example, create one PubSubController for each  I and then create a Haskell thread bound to each capability each calling e in a loop. This will create one network connection per controller/capability and allow you to register separate channels and callbacks for each controller, spreading the load across the capabilities. XhedischannelhedismessageYhedischannelZhedischannel[hedispattern\hedispattern]hedisInitial subscriptions.hedisCallback function.^hedisthe initial subscriptionshedis!the initial pattern subscriptionsahedisthe channels to subscribe tohedis$the channels to pattern subscribe tobhedisthe channels to subscribe tohedisthe channels to psubscribe toehedisThe connection poolhedisBThe controller which keeps track of all subscriptions and handlershedisThis action is executed once Redis acknowledges that all the subscriptions in the controller are now subscribed. You can use this after an exception (such as ConnectionLost7) to signal that all subscriptions are now reactivated.KLMNOPQRSTUVWXYZ[\]^_`abcdeNone"#>z hedisOptions for the  command.hedisOptions for the  command.hedis A single entry from the slowlog.hedis9A unique progressive identifier for every slow log entry.hedis=The unix timestamp at which the logged command was processed.hedis=The amount of time needed for its execution, in microseconds.hedisThe command and it's arguments.hedisRedis default 1. Equivalent to omitting all optional parameters.  SortOpts { sortBy = Nothing -- omit the BY option , sortLimit = (0,-1) -- return entire collection , sortGet = [] -- omit the GET option , sortOrder = Asc -- sort in ascending order , sortAlpha = False -- sort numerically, not lexicographically } hedisRedis default 1. Equivalent to omitting all optional parameters. MigrateOpts { migrateCopy = False -- remove the key from the local instance , migrateReplace = False -- don't replace existing key on the remote instance } hedisRedis default 1. Equivalent to omitting all optional parameters.  ZaddOpts { zaddCondition = Nothing -- omit NX and XX options , zaddChange = False -- don't modify the return value from the number of new elements added, to the total number of elements changed , zaddIncrement = False -- don't add like ZINCRBY } hedisRedis default 1. Equivalent to omitting all optional parameters. ScanOpts { scanMatch = Nothing -- don't match any pattern , scanCount = Nothing -- don't set any requirements on number elements returned (works like value COUNT 10) } hedisRedis default 1. Equivalent to omitting all optional parameters. XReadOpts { block = Nothing -- Don't block waiting for more records , recordCount = Nothing -- no record count } hedisFormat a request for XCLAIM.Uhediskeyhediskeyhediskeyhediskeyhedispivothedisvaluehediskeyhedispivothedisvaluehediskeyhediscnthediskeyhedisstarthedisstophediskeyhedisstarthedisstophediskeyhedisstarthedisstophediskeyhedisstarthedisstophediskeyhedisminhedismaxhediskeyhedisminhedismaxhediskeyhedisminhedismaxhedisoffsethediscounthediskeyhedisminhedismaxhedisoffsethediscounthediskeyhedismaxhedisminhediskeyhedismaxhedisminhediskeyhedismaxhedisminhedisoffsethediscounthediskeyhedismaxhedisminhedisoffsethediscounthediskeyhedis destinationhediskeyhediskeyhedis destinationhedis destinationhediskeyshedis destinationhedis weighted keyshedis destinationhediskeyshedis destinationhedis weighted keyshediscmdhedis destinationhediskeyshedisweightshedisscripthediskeyshedisargshedisscripthediskeyshedisargshediskeyhediskeyhedisstarthedisendhedisdestkeyhedissrckeyshedisdestkeyhedissrckeyshedisdestkeyhedissrckeyshedisdestkeyhedissrckeyhedis operationhediskeyshedishosthedisporthediskeyhedis destinationDbhedistimeouthedishosthedisporthedis destinationDbhedistimeouthediskeyshediskeyhedis timeToLivehedisserializedValuehediskeyhedis timeToLivehedisserializedValuehediskeyhedisvaluehediskeyhedisvaluehediskeyhedis scoreMemberhediskeyhedis scoreMemberhedisoptionshediskeyhediskeyhediscounthediskeyhediskeyhediscounthedissectionhediskeyhedisnext cursor and values hedisnext cursor and valueshedismain part of scan command hediskeyhedisnext cursor and values hediskeyhedisnext cursor and values hediskeyhedisnext cursor and values hediskeyhedisnext cursor and valueshediskeyhedisnext cursor and valueshediskeyhedisnext cursor and valueshediskeyhedisminhedismaxhediskeyhedisminhedismaxhedisoffsethediscounthediskeyhedisidhedis(field, value)hedisstreamhedisidhedis(field, value)hedis(stream, id) pairshedisOptionshedis(stream, id) pairshedis group namehedis consumer namehedis(stream, id) pairshedisOptionshedis group namehedis consumer namehedis(stream, id) pairshedisstreamhedis group namehedisstart IDhedisstreamhedisgrouphedisidhedisstreamhedisgrouphedisconsumerhedisstreamhedisgrouphedisstreamhedis group namehedis message IDshedisstreamhedisstarthedisendhedisCOUNThedisstreamhedisendhedisstarthedisCOUNT hedisstream!hedisstreamhedisgrouphedisconsumer"hedisstreamhedisgrouphedisstartIdhedisendIdhediscounthedisconsumerhedisstreamhedisgrouphedisconsumerhedis min idle timehedisoptional argumentshedis message IDs$hedisstreamhedisgrouphedisconsumerhedis min idle timehedisoptional argumentshedis message IDs%hedisstreamhedisgrouphedisconsumerhedis min idle timehedisoptional argumentshedis message IDs&hedisstreamhedisgroup'hedisstream(hedisstream)hedisstreamhedis message IDs*hedisstreamfgnmlkjihoptsrquvyxwz{~}|      !"#$%&'()*+None>d,hediskey-hediskeyhedisvalue.hediskey0hedisconnectionName1hediskeyhedismember2hediskeyhedisminhedismax3hediskey4hedishosthedisport5hediskeyhedisvalue6hediskey8hediskey9hedissourcehedis destination:hediskeyhedistimeout<hediskeyhedis incrementhedismember=hediskey>hediskeyhedis fieldValue?hediskey@hediskeyhedisvalueAhediskeyhedisstarthedisstopChediskeyhedismemberDhediskeyhedisindexEhediskeyhedisvalueFhediskeyhedisfieldGhedissourcehedis destinationhedismemberHhediskeyhedismemberJhediskeyKhediskeyhedisfieldLhediskeyhedis incrementMhediskeyhedisoffsethedisvalueOhediskeyhedis incrementQhediskeyRhediskeyhedisminhedismaxShediskeyThedis destinationhediskeyUhediskeyVhedis parameterhedisvalueYhedis numslaveshedistimeoutZhediskey[hedistimeout\hediskeyhedisseconds]hediskey^hediskeyhedisbithedisstarthedisend`hediskeyhedis millisecondsbhediskeyhedisnewkeychedisdestkeyhedis sourcekeydhediskeyhediscounthedisvalueehediskeyfhediskeyghediskeyhedisstarthedisendhhedis destinationhediskeyihediskeyhedisminhedismaxjhedisscriptkhediskeyhedisvaluelhediskeymhedispatternnhedis parameterohediskeyhedisvalueqhediskeyhedisfieldhedisvaluerhediskeyValueshediskeyhedissecondshedisvaluethediskeyhedis millisecondshedisvalueuhediskeyvhedisscriptwhedis destinationhediskeyxhediskeyyhediskeyzhediskeyhedisvalue{hediskeyhedisfieldhedisvalue|hedissourcehedis destinationhedistimeout}hediskeyhedismemberhediskeyhedisoffsethedisvaluehediskeyhediskeyhedisfieldhedis incrementhediskeyhedisfieldhedis incrementhediskeyhedisminhedismaxhediskeyhediskeyhedisnewkeyhediskeyhedismemberhediskeyhedisfieldhediskeyhediskeyhedisfieldhediskeyhedisstarthedisstophediskeyhedis decrementhediskeyhediskeyhedisvaluehediskeyhediskeyhedisfieldhediskeyhedismillisecondsTimestamphediskeyhedisstarthedisstophediskeyhediskeyhedisindexhedisvaluehediskeyhedis timestamphediskeyhedisdbhediskeyhedisoffsethediskeyValuehedis commandNamehediskeyhedistimeouthediskeyhedismemberhedismessagehediskeyhedismemberE?@Afghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~None@hedisParse a & from a URL:Username is ignored, path is used to specify the database:6parseConnectInfo "redis://username:password@host:42/2"Right (ConnInfo {connectHost = "host", connectPort = PortNumber 42, connectAuth = Just "password", connectDatabase = 2, connectMaxConnections = 50, connectMaxIdleTime = 30s, connectTimeout = Nothing, connectTLSParams = Nothing})7parseConnectInfo "redis://username:password@host:42/db"Left "Invalid port: db"=The scheme is validated, to prevent mixing up configurations:parseConnectInfo "postgres://"Left "Wrong scheme"EBeyond that, all values are optional. Omitted values are taken from 9:parseConnectInfo "redis://"Right (ConnInfo {connectHost = "localhost", connectPort = PortNumber 6379, connectAuth = Nothing, connectDatabase = 0, connectMaxConnections = 50, connectMaxIdleTime = 30s, connectTimeout = Nothing, connectTLSParams = Nothing})None{  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~56734120#$%:;<=>&'()*+,-./9 ?A@l\mx`.pb ,YK=38>  {qFU@Jc:|DZEzd9o5vW~j;7a[0/nIVX6NB_4PCueh?TQG  Swi<R1A2}H^fgkOL]rtMs-y !"z{|}~#$%uvwxy&opqrst'fghijklmn()*+HIJFBCDEGX]QRSTUVWYZ[\ePONMK^_`abcdL8 !"  !"#$%&'()*+,-./-0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_``abcdefghijklmnopqrsttuvwxyz{||}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~?IK$hedis-0.12.13-LQFQbfxNSHo3tW6E4DobsuDatabase.RedisDatabase.Redis.Core.InternalDatabase.Redis.Protocol!Database.Redis.ProtocolPipeliningDatabase.Redis.TypesDatabase.Redis.CoreDatabase.Redis.TransactionsDatabase.Redis.PubSubControl.Concurrent killThreadControl.Concurrent.AsynccancelgetNumCapabilitiesDatabase.Redis.ManualCommandsDatabase.Redis.CommandsDatabase.Redis.URLReply SingleLineErrorIntegerBulk MultiBulkConnectionLostExceptionConnectionLostPortID PortNumber UnixSocketRedisEnvEnvenvConn envLastReplyRedis $fMonadRedis$fMonadIORedis$fFunctorRedis$fApplicativeRedis$fMonadFailRedis RedisTypeNoneStringHashListSetZSetStatusOkPong RedisResultdecode ConnectErrorConnectAuthErrorConnectSelectError ConnectInfoConnInfo connectHost connectPort connectAuthconnectDatabaseconnectMaxConnectionsconnectMaxIdleTimeconnectTimeoutconnectTLSParams Connection MonadRedis liftRedisRedisCtx returnDecoderunRedisunRedisreRedis sendRequestdefaultConnectInfoconnectcheckedConnect disconnect withConnectwithCheckedConnectauthselectpingTxResult TxSuccess TxAbortedTxErrorQueuedRedisTxwatchunwatch multiExecPubSubControllerUnregisterCallbacksActionPMessageCallbackMessageCallback RedisPChannel RedisChannelMessagePMessage msgChannel msgMessage msgPatternPubSubpublish subscribe unsubscribe psubscribe punsubscribepubSubnewPubSubControllercurrentChannelscurrentPChannels addChannelsaddChannelsAndWaitremoveChannelsremoveChannelsAndWait pubSubForeverXInfoStreamResponsexinfoStreamLengthxinfoStreamRadixTreeKeysxinfoStreamRadixTreeNodesxinfoStreamNumGroupsxinfoStreamLastEntryIdxinfoStreamFirstEntryxinfoStreamLastEntryXInfoGroupsResponsexinfoGroupsGroupNamexinfoGroupsNumConsumersxinfoGroupsNumPendingMessages!xinfoGroupsLastDeliveredMessageIdXInfoConsumersResponsexinfoConsumerNamexinfoConsumerNumPendingMessagesxinfoConsumerIdleTime XClaimOpts xclaimIdle xclaimTimexclaimRetryCount xclaimForceXPendingDetailRecord messageIdconsumermillisSinceLastDeliverednumTimesDeliveredXPendingSummaryResponsenumPendingMessagessmallestPendingMessageIdlargestPendingMessageIdnumPendingMessagesByconsumer XReadResponsestreamrecords XReadOptsblock recordCount StreamsRecordrecordId keyValuesTrimOptsNoArgsMaxlen ApproxMaxlenRangeLexInclExclMinrMaxrScanOpts scanMatch scanCountCursor ReplyModeZaddOpts zaddCondition zaddChange zaddIncrement DebugModeSetOpts setSecondssetMilliseconds setCondition ConditionNxXx MigrateOpts migrateCopymigrateReplace AggregateSumMinMax SortOrderAscDescSortOptssortBy sortLimitsortGet sortOrder sortAlphaSlowlog slowlogIdslowlogTimestamp slowlogMicros slowlogCmdslowlogClientIpAndPortslowlogClientNameobjectRefcountobjectIdletimeobjectEncoding linsertBefore linsertAftergetType slowlogGet slowlogLen slowlogResetzrangezrangeWithscores zrevrangezrevrangeWithscores zrangebyscorezrangebyscoreWithscoreszrangebyscoreLimitzrangebyscoreWithscoresLimitzrevrangebyscorezrevrangebyscoreWithscoreszrevrangebyscoreLimitzrevrangebyscoreWithscoresLimitdefaultSortOpts sortStoresort zunionstorezunionstoreWeights zinterstorezinterstoreWeightsevalevalshabitcount bitcountRangebitopAndbitopOrbitopXorbitopNotmigratedefaultMigrateOptsmigrateMultiplerestorerestoreReplacesetsetOpts scriptDebugzadddefaultZaddOptszaddOpts clientReply srandmember srandmemberNspopspopNinfo infoSectionexistscursor0scandefaultScanOptsscanOptssscan sscanOptshscan hscanOptszscan zscanOpts zrangebylexzrangebylexLimitxaddOptsxadddefaultXreadOpts xreadOptsxreadxreadGroupOpts xreadGroup xgroupCreate xgroupSetIdxgroupDelConsumer xgroupDestroyxackxrange xrevRangexlenxpendingSummaryxpendingDetaildefaultXClaimOptsxclaim xclaimJustIdsxinfoConsumers xinfoGroups xinfoStreamxdelxtriminfttlsetnxpttl commandCount clientSetnamezrankzremrangebyscorehkeysslaveofrpushx debugObjectbgsavehlen rpoplpushbrpop bgrewriteaofzincrbyhgetallhmsetsinterpfaddzremrangebyrankflushdbsaddlindexlpushhstrlensmovezscoreconfigResetstatpfcounthdel incrbyfloatsetbitflushallincrbytimesmembers zlexcountsunion sinterstorehvals configSet scriptFlushdbsizewaitlpop clientPauseexpiremgetbitposlastsavepexpire clientListrenamenxpfmergelremsdiffgetgetrange sdiffstorezcount scriptLoadgetsetdumpkeys configGetrpush randomkeyhsetnxmsetsetexpsetexscard scriptExists sunionstorepersiststrlenlpushxhset brpoplpushzrevrank scriptKillsetrangedel hincrbyfloathincrbyzremrangebylexrpoprenamezremhexists clientGetname configRewritedecrhmgetlrangedecrbyllenappendincrhget pexpireatltrimzcardlsetexpireatsavemovegetbitmsetnx commandInfoquitblpopsremecho sismemberparseConnectInfo renderRequestreplyconnCtx connReplies connPendingconnPendingCntsendbaseGHC.IO.Handle.TypesHandle GHC.IO.HandlehFlushrecvflushrequestconnGetReplies GHC.IO.UnsafeunsafeInterleaveIO enableTLSbeginReceiving Data.EitherEitherRedisArgencode GHC.MaybeJustrunRedisInternalConnGHC.BaseFunctor ApplicativeMonad stm-2.5.0.0Control.Concurrent.STM.TBQueueTBQueuememptyMonoidmappendmconcat PubSubState unsubChannels listenThread sendThread xclaimRequest sortInternalzstoreInternalbitop addScanOptsOffOnSkipNoSyncYesinternalXreadArgs