-- | A model for categorizing Redis commands for their particular structures using a GADT. module HLRDB.Primitives.Redis where import Data.Functor.Identity import Data.ByteString -- | List and SSet declarations allow you to provide a TrimScheme. When provided, HLRDB will automatically trim the structure to the desired cardinality whenever data is inserted. -- -- For example, if you set a softCardinality of 100 and a trimProbability of 0.05, whenever a data insertion takes place that could bring the cardinality over 100, there will be a 5% chance that a trim command will also be executed. If you want a hard cardinality (to the extent that Redis provides any guarantees), simply set the probability to 1. If you do not want any automatic trimming, simply do not provide a TrimScheme. data TrimScheme = TrimScheme { TrimScheme -> Integer softCardinality :: Integer , TrimScheme -> Double trimProbability :: Double } -- | GADT declaring the major Redis data structures. For application-level logic, the simpler type aliases declared below should suffice. data RedisStructure t a b where RKeyValue :: E Maybe a b -> RedisStructure (BASIC ()) a b -- Do not allow specifying an encoding for Integer, since Redis commands like incr -- demand that *only* the standard encoding is used, e.g., 123 -> "123" RKeyValueInteger :: (a -> ByteString) -> (b -> Integer) -> (Integer -> b) -> RedisStructure (BASIC Integer) a b RKeyValueByteString :: (a -> ByteString) -> RedisStructure (BASIC ByteString) a ByteString RList :: RE a b -> Maybe TrimScheme -> RedisStructure LIST a b RHSet :: RE a b -> HSET v -> RedisStructure (HSET v) a b RSet :: RE a b -> RedisStructure SET a b RSortedSet :: RE a b -> Maybe TrimScheme -> RedisStructure SORTEDSET a b -- | Alias for simple key-value storage type RedisBasic k v = RedisStructure (BASIC ()) k v -- | Alias for simple Integer storage type RedisIntegral k v = RedisStructure (BASIC Integer) k v -- | Alias for indexable ByteString storage, allowing getting and setting ranges within the value. To enforce consistency across the low-level getrange/setrange commands, non-existent values are transparently rendered as empty ByteStrings. Note that the maximum size permitted in a single value by Redis is 512 MB. type RedisByteString k v = RedisStructure (BASIC ByteString) k ByteString -- | Alias for a Redis List type RedisList k v = RedisStructure LIST k v -- | Alias for a Redis HSet type RedisHSet k s v = RedisStructure (HSET s) k v -- | Alias for a Redis Set type RedisSet k v = RedisStructure SET k v -- | Alias for a Redis SortedSet type RedisSSet k v = RedisStructure SORTEDSET k v -- | Many commands in Redis return information about whether items were added/removed or merely updated data ActionPerformed a where FreshlyCreated :: Integer -> ActionPerformed Creation Deleted :: Integer -> ActionPerformed Deletion -- | General primitive encoding. We need a way to serialize the key, and a way to both serialize and deserialize values. data E f a b = E (a -> ByteString) (b -> f ByteString) (f ByteString -> b) -- | Most structures don't rely on any special context type RE a b = E Identity a b -- | Type-level indicator for Redis basic types data BASIC a -- | Type-level indicator for Redis Lists data LIST -- | Type-level indicator for Redis HSets with sub-keys of type k; requires a way to serialize and deserialize sub-keys data HSET k = HSET (k -> ByteString) (ByteString -> k) -- | Type-level indicator for Redis Sets data SET -- | Type-level indicator for Redis SortedSets data SORTEDSET -- | Type-level indicator for Creation data Creation -- | Type-level indicator for Deletion data Deletion