{-# LANGUAGE GeneralizedNewtypeDeriving #-}moduleDatabase.Redis.Internal(HostName,PortID(..),defaultPort,RedisConn(),connect,disconnect,Redis(),runRedis,send,recv,sendRequest)whereimportControl.ApplicativeimportControl.Monad.RWSimportControl.ConcurrentimportqualifiedData.ByteStringasBimportqualifiedData.ByteString.Lazy.Char8asLBimportNetwork(HostName,PortID(..),connectTo)importSystem.IO(Handle,hFlush,hClose,hIsOpen)importDatabase.Redis.ReplyimportDatabase.Redis.RequestimportDatabase.Redis.Types-------------------------------------------------------------------------------- Connection---- |Connection to a Redis server. Use the 'connect' function to create one.---- A 'RedisConn' can only be used by a single thread at a time. This means that-- calls to 'runRedis' or 'disconnet' may block when the 'RedisConn' is shared-- between multiple threads.dataRedisConn=Conn(MVar(Handle,[Reply]))withConn::RedisConn->(Handle->[Reply]->IO([Reply],a))->IOawithConn(Connconn)f=do(h,rs)<-takeMVarconn(rs',a)<-fhrsputMVarconn(h,rs')returna-- |Opens a connection to a Redis server at the given host and port.connect::HostName->PortID->IORedisConnconnecthostport=doh<-connectTohostportreplies<-parseReply<$>LB.hGetContentshConn<$>newMVar(h,replies)-- |Close the given connection.---- May block when the given 'RedisConn' is shared between multiple threads. The-- 'RedisConn' can not be re-used.disconnect::RedisConn->IO()disconnectconn=withConnconn$\hrs->doopen<-hIsOpenhwhenopen(hCloseh)return(rs,())-- | The Redis default port 6379. Equivalent to @'PortNumber' 6379@.defaultPort::PortIDdefaultPort=PortNumber6379-------------------------------------------------------------------------------- The Redis Monad--newtypeRedisa=Redis(RWSTHandle()[Reply]IOa)deriving(Monad,MonadIO,Functor,Applicative)-- |Interact with a Redis datastore specified by the given 'RedisConn'.---- May block when the given 'RedisConn' is shared between multiple threads.runRedis::RedisConn->Redisa->IOarunRedisconn(Redisredis)=withConnconn$\hrs->doopen<-hIsOpenhifopenthendo(a,rs',_)<-runRWSTredishrsreturn(rs',a)elseerror"Redis: disconnected"send::[B.ByteString]->Redis()sendreq=Redis$doh<-askliftIO$doB.hPuth$renderRequestreqhFlushhrecv::RedisReplyrecv=Redis$do-- head/tail avoids forcing the ':' constructor, enabling automatic-- pipelining.rs<-getput(tailrs)return(headrs)-- |Sends a request to the Redis server, returning the 'decode'd reply.sendRequest::(RedisResulta)=>[B.ByteString]->Redis(EitherReplya)sendRequestreq=decode<$>(sendreq>>recv)