| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Network.Memcached: A Memcached client implementation in Haskell.
Supports the most popular memcached commands, including set, add, replace, get, delete, incr, and decr.
Memcached protocol and command reference: https://github.com/memcached/memcached/blob/master/doc/protocol.txt
Based off an original work by "olegkat": https://github.com/olegkat/haskell-memcached
Most importantly, Network.Memcached attempts to increase the safety of memcached's intentionally loose protocol.
For example, memcached's exptime is a stringified integer value that could mean:
In any non-trivial application, it's hard, if not impossible, to guarantee that exptime won't be accidentally interpreted by the wrong assumption, either through misconfiguration or computation.
To weaken this footgun, Network.Memcached uses an algebraic data type:
data Expiry =
Never |
Asap |
Seconds Word32 |
Date UTCTimeBy choosing the appropriate constructor, developers avoid accidentally wandering into the wrong exptime assumption, and computations are performed in the correct data type (Word32 or UTCTime).
You may have noticed that there's still a way to make a mistake. Specifically, using the Seconds constructor with a value greater then 30 days: let exp = Seconds 2592001. The current codebase handles this at run-time (unfortunately), by clipping the Seconds value to the range 1..2592000.
I've recently discovered Refined, which could be a great way to restrict the Seconds value to the correct range at compile time. PR, anyone?
(Coincidentally, the Date constructor doesn't have quite the same problem. The only potentially problematic dates are the unix epoch (1970-01-01T00:00:00) and the following 30 days. It would be ideal to handle the Date constructor with a refined type, too, even if these dates are more unlikely to affect a well-designed application.)
Network.Memcached also prevents improper connection setup via a useful GADT. The Server c data type is parameterized by connection state.
The only way to call memcached commands is on a Server Connection (ignoring Server AutoConnection for the moment). The easiest way to obtain a Server Connection is via connect, which expects a Server NoConnection as input, and the easiest way to obtain a Server NoConnection is to call configure with the appropriate configuration settings.
The following flow is ensured to be correct without any loss of flexibility:
configure --> connect --> --> disconnect
You simply can't call connect without a properly configured, disconnected server, and you can't mistakenly reuse an old, possibly disconnected connection. (See the Network.Memcached.Server module.)
Auto-connection works similarly. Clustering is also integrated with the Server GADT. (See Clustering below.)
Clustering support has been added (see Network.Memcached.Cluster), but only supports an overly simplistic hashing algorithm at the moment. If anybody wants to submit a PR for ketama support, that would be awesome!
The cachedOp function in Network.Memcached.Helpers may be used to transform a simple key-value IO operation (k -> IO v) into a key-value IO operation that caches key-value pairs via memcached.
Example:
-- `cachedDbOp` can now be used wherever `normalDbOp` can be used.
let cachedDbOp = cachedOp normalDbOp connectedServerHere's one way to use this lib. See the Network.Memcached.Server module for more info.
-- Sample creation:
do
let defaultValue = "foo"
-- `configure` a "prototype" connection to generate connected clients
let host = "memcached-server"
port = 1234
proto = configure (Seconds 120) Nothing
-- `connect` to the memcached server.
mc <- connect proto host (Just port)
-- `get` a value for a specific `key`.
cached <- get mc key
-- Check if we got it.
case cached of
Just es -> do
-- Got it! Convert from string to intended type.
return $ read es
Nothing -> do
-- You could do all sorts of things here, such as calculate and
-- store the value in memcached (via the `set` command), for instance.
-- We'll just return a default value:
return defaultValueImplementors should consider using System.Timeout (timeout) to detect hung servers.
| Back | FazBrowse Home | New Git URL |