@@ -15,6 +15,7 @@ module Database.Redis.Cluster
15
15
, disconnect
16
16
, requestPipelined
17
17
, nodes
18
+ , hooks
18
19
) where
19
20
20
21
import qualified Data.ByteString as B
@@ -36,6 +37,7 @@ import System.IO.Unsafe(unsafeInterleaveIO)
36
37
37
38
import Database.Redis.Protocol (Reply (Error ), renderRequest , reply )
38
39
import qualified Database.Redis.Cluster.Command as CMD
40
+ import Database.Redis.Hooks (Hooks )
39
41
40
42
-- This module implements a clustered connection whilst maintaining
41
43
-- compatibility with the original Hedis codebase. In particular it still
@@ -48,7 +50,7 @@ import qualified Database.Redis.Cluster.Command as CMD
48
50
49
51
-- | A connection to a redis cluster, it is compoesed of a map from Node IDs to
50
52
-- | 'NodeConnection's, a 'Pipeline', and a 'ShardMap'
51
- data Connection = Connection (HM. HashMap NodeID NodeConnection ) (MVar Pipeline ) (MVar ShardMap ) CMD. InfoMap
53
+ data Connection = Connection (HM. HashMap NodeID NodeConnection ) (MVar Pipeline ) (MVar ShardMap ) CMD. InfoMap Hooks
52
54
53
55
-- | A connection to a single node in the cluster, similar to 'ProtocolPipelining.Connection'
54
56
data NodeConnection = NodeConnection CC. ConnectionContext (IOR. IORef (Maybe B. ByteString )) NodeID
@@ -100,13 +102,13 @@ instance Exception UnsupportedClusterCommandException
100
102
newtype CrossSlotException = CrossSlotException [[B. ByteString ]] deriving (Show , Typeable )
101
103
instance Exception CrossSlotException
102
104
103
- connect :: [CMD. CommandInfo ] -> MVar ShardMap -> Maybe Int -> IO Connection
104
- connect commandInfos shardMapVar timeoutOpt = do
105
+ connect :: [CMD. CommandInfo ] -> MVar ShardMap -> Maybe Int -> Hooks -> IO Connection
106
+ connect commandInfos shardMapVar timeoutOpt hooks' = do
105
107
shardMap <- readMVar shardMapVar
106
108
stateVar <- newMVar $ Pending []
107
109
pipelineVar <- newMVar $ Pipeline stateVar
108
110
nodeConns <- nodeConnections shardMap
109
- return $ Connection nodeConns pipelineVar shardMapVar (CMD. newInfoMap commandInfos) where
111
+ return $ Connection nodeConns pipelineVar shardMapVar (CMD. newInfoMap commandInfos) hooks' where
110
112
nodeConnections :: ShardMap -> IO (HM. HashMap NodeID NodeConnection )
111
113
nodeConnections shardMap = HM. fromList <$> mapM connectNode (nub $ nodes shardMap)
112
114
connectNode :: Node -> IO (NodeID , NodeConnection )
@@ -116,14 +118,14 @@ connect commandInfos shardMapVar timeoutOpt = do
116
118
return (n, NodeConnection ctx ref n)
117
119
118
120
disconnect :: Connection -> IO ()
119
- disconnect (Connection nodeConnMap _ _ _) = mapM_ disconnectNode (HM. elems nodeConnMap) where
121
+ disconnect (Connection nodeConnMap _ _ _ _ ) = mapM_ disconnectNode (HM. elems nodeConnMap) where
120
122
disconnectNode (NodeConnection nodeCtx _ _) = CC. disconnect nodeCtx
121
123
122
124
-- Add a request to the current pipeline for this connection. The pipeline will
123
125
-- be executed implicitly as soon as any result returned from this function is
124
126
-- evaluated.
125
127
requestPipelined :: IO ShardMap -> Connection -> [B. ByteString ] -> IO Reply
126
- requestPipelined refreshAction conn@ (Connection _ pipelineVar shardMapVar _) nextRequest = modifyMVar pipelineVar $ \ (Pipeline stateVar) -> do
128
+ requestPipelined refreshAction conn@ (Connection _ pipelineVar shardMapVar _ _ ) nextRequest = modifyMVar pipelineVar $ \ (Pipeline stateVar) -> do
127
129
(newStateVar, repliesIndex) <- hasLocked $ modifyMVar stateVar $ \ case
128
130
Pending requests | isMulti nextRequest -> do
129
131
replies <- evaluatePipeline shardMapVar refreshAction conn requests
@@ -228,7 +230,7 @@ retryBatch shardMapVar refreshShardmapAction conn retryCount requests replies =
228
230
-- there is one.
229
231
case last replies of
230
232
(Error errString) | B. isPrefixOf " MOVED" errString -> do
231
- let (Connection _ _ _ infoMap) = conn
233
+ let (Connection _ _ _ infoMap _ ) = conn
232
234
keys <- mconcat <$> mapM (requestKeys infoMap) requests
233
235
hashSlot <- hashSlotForKeys (CrossSlotException requests) keys
234
236
nodeConn <- nodeConnForHashSlot shardMapVar conn (MissingNodeException (head requests)) hashSlot
@@ -250,7 +252,7 @@ retryBatch shardMapVar refreshShardmapAction conn retryCount requests replies =
250
252
evaluateTransactionPipeline :: MVar ShardMap -> IO ShardMap -> Connection -> [[B. ByteString ]] -> IO [Reply ]
251
253
evaluateTransactionPipeline shardMapVar refreshShardmapAction conn requests' = do
252
254
let requests = reverse requests'
253
- let (Connection _ _ _ infoMap) = conn
255
+ let (Connection _ _ _ infoMap _ ) = conn
254
256
keys <- mconcat <$> mapM (requestKeys infoMap) requests
255
257
-- In cluster mode Redis expects commands in transactions to all work on the
256
258
-- same hashslot. We find that hashslot here.
@@ -296,7 +298,7 @@ evaluateTransactionPipeline shardMapVar refreshShardmapAction conn requests' = d
296
298
297
299
nodeConnForHashSlot :: Exception e => MVar ShardMap -> Connection -> e -> HashSlot -> IO NodeConnection
298
300
nodeConnForHashSlot shardMapVar conn exception hashSlot = do
299
- let (Connection nodeConns _ _ _) = conn
301
+ let (Connection nodeConns _ _ _ _ ) = conn
300
302
(ShardMap shardMap) <- hasLocked $ readMVar shardMapVar
301
303
node <-
302
304
case IntMap. lookup (fromEnum hashSlot) shardMap of
@@ -339,12 +341,12 @@ moved _ = False
339
341
340
342
341
343
nodeConnWithHostAndPort :: ShardMap -> Connection -> Host -> Port -> Maybe NodeConnection
342
- nodeConnWithHostAndPort shardMap (Connection nodeConns _ _ _) host port = do
344
+ nodeConnWithHostAndPort shardMap (Connection nodeConns _ _ _ _ ) host port = do
343
345
node <- nodeWithHostAndPort shardMap host port
344
346
HM. lookup (nodeId node) nodeConns
345
347
346
348
nodeConnectionForCommand :: Connection -> ShardMap -> [B. ByteString ] -> IO [NodeConnection ]
347
- nodeConnectionForCommand conn@ (Connection nodeConns _ _ infoMap) (ShardMap shardMap) request =
349
+ nodeConnectionForCommand conn@ (Connection nodeConns _ _ infoMap _ ) (ShardMap shardMap) request =
348
350
case request of
349
351
(" FLUSHALL" : _) -> allNodes
350
352
(" FLUSHDB" : _) -> allNodes
@@ -364,7 +366,7 @@ nodeConnectionForCommand conn@(Connection nodeConns _ _ infoMap) (ShardMap shard
364
366
Just allNodes' -> return allNodes'
365
367
366
368
allMasterNodes :: Connection -> ShardMap -> Maybe [NodeConnection ]
367
- allMasterNodes (Connection nodeConns _ _ _) (ShardMap shardMap) =
369
+ allMasterNodes (Connection nodeConns _ _ _ _ ) (ShardMap shardMap) =
368
370
mapM (flip HM. lookup nodeConns . nodeId) masterNodes
369
371
where
370
372
masterNodes = (\ (Shard master _) -> master) <$> nub (IntMap. elems shardMap)
@@ -410,3 +412,6 @@ hasLocked action =
410
412
action `catches`
411
413
[ Handler $ \ exc@ BlockedIndefinitelyOnMVar -> throwIO exc
412
414
]
415
+
416
+ hooks :: Connection -> Hooks
417
+ hooks (Connection _ _ _ _ h) = h
0 commit comments