hask-redis-mux-0.1.0.0: lib/cluster/Database/Redis/Cluster/Commands.hs
{-# LANGUAGE OverloadedStrings #-}
-- | Shared command classification for cluster routing
-- This module provides lists of Redis commands categorized by their routing requirements
--
-- @since 0.1.0.0
module Database.Redis.Cluster.Commands
( keylessCommands,
requiresKeyCommands,
CommandRouting (..),
classifyCommand,
)
where
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BS8
import Data.Char (toUpper)
-- | Result of classifying a command for cluster routing
data CommandRouting
= KeylessRoute -- ^ Route to any master node
| KeyedRoute ByteString -- ^ Route by this key's hash slot
| CommandError String -- ^ Invalid command (e.g., missing required key)
-- | Classify a Redis command for cluster routing.
-- Returns 'KeylessRoute' for commands like PING or AUTH that can go to any master,
-- 'KeyedRoute' with the routing key for commands that target a specific slot,
-- or 'CommandError' if a key-requiring command is missing its key argument.
classifyCommand :: ByteString -> [ByteString] -> CommandRouting
classifyCommand cmd args =
let cmdUpper = BS8.map toUpper cmd
in if cmdUpper `elem` keylessCommands
then KeylessRoute
else case args of
[] -> if cmdUpper `elem` requiresKeyCommands
then CommandError $ "Command " ++ BS8.unpack cmd ++ " requires a key argument"
else KeylessRoute -- Unknown command without args, try keyless
(key:_) -> KeyedRoute key
-- | Commands that don't require a key argument (route to any master node)
-- These commands can be executed on any master node in the cluster
-- Note: This list is based on Redis 7.x commands and may need updates for newer versions
-- See CLUSTERING_IMPLEMENTATION_PLAN.md Phase 17 for future work on eliminating this hardcoded list
keylessCommands :: [ByteString]
keylessCommands =
[ "PING",
"AUTH",
"FLUSHALL",
"FLUSHDB",
"DBSIZE",
"CLUSTER",
"INFO",
"TIME",
"CLIENT",
"CONFIG",
"BGREWRITEAOF",
"BGSAVE",
"SAVE",
"LASTSAVE",
"SHUTDOWN",
"SLAVEOF",
"REPLICAOF",
"ROLE",
"ECHO",
"SELECT",
"QUIT",
"COMMAND"
]
-- | Commands that require a key argument (route by key's hash slot)
-- These commands must be routed to the node responsible for the key's hash slot
-- Note: This list is based on Redis 7.x commands and may need updates for newer versions
-- See CLUSTERING_IMPLEMENTATION_PLAN.md Phase 17 for future work on eliminating this hardcoded list
requiresKeyCommands :: [ByteString]
requiresKeyCommands =
[ "GET",
"SET",
"DEL",
"EXISTS",
"INCR",
"DECR",
"HGET",
"HSET",
"HDEL",
"HKEYS",
"HVALS",
"HGETALL",
"HEXISTS",
"LPUSH",
"RPUSH",
"LPOP",
"RPOP",
"LRANGE",
"LLEN",
"LINDEX",
"SADD",
"SREM",
"SMEMBERS",
"SCARD",
"SISMEMBER",
"ZADD",
"ZREM",
"ZRANGE",
"ZCARD",
"EXPIRE",
"TTL",
"PERSIST",
"MGET",
"MSET",
"SETNX",
"PSETEX",
"APPEND",
"GETRANGE",
"SETRANGE",
"STRLEN",
"GETEX",
"GETDEL",
"SETEX"
]