An LFE Redis Client Library
Dependences ↟
You will need the following installed on your system:
- Erlang
- Redis
- rebar3
Installtion and Setup ↟
Here's what you need to do:
$ git clone https://github.com/lfex/ledis.git
$ cd ledis
$ make compileAt this point, you will be able to run an LFE REPL (shell):
$ make replIf you don't have access to a Rdis deployment, you can always do this:
$ docker run --rm -p 6379:6379 redis:latestUsage ↟
To use ledis from the shell, just do this:
$ make replNote that, under the hood, this will activate the "dev" profile, so LFE and some developer rebar3 LFE plugins will be downloaded the first time it is run.
Erlang/OTP 24 [erts-12.0.2] [source] [64-bit] [smp:4:4] ...
..-~.~_~---..
( \\ ) | A Lisp-2+ on the Erlang VM
|`-.._/_\\_.-': | Type (help) for usage info.
| g |_ \ |
| n | | | Docs: http://docs.lfe.io/
| a / / | Source: http://github.com/lfe/lfe
\ l |_/ |
\ r / | LFE v2.0.1 (abort with ^G)
`-E___.-'
lfe>lfe> (ledis:start-link)
true
lfe> (ledis:get 'foo)
#(ok undefined)
lfe> (ledis:set 'foo 'bar)
#(ok #"OK")
lfe> (ledis:get 'foo)
#(ok #"bar")You may also provide an option to convert all results to string values:
lfe> (ledis:set 'foo 'bar '(#(return-type string)))
#(ok "OK")
lfe> (ledis:get 'foo '(#(return-type string)))
#(ok "bar")If you would like to receive string values by default, simply update either
your project's lfe.config or your ~/.lfe/lfe.config file with the
following:
#(ledis
(#(client-process-name ledis-client)
#(return-type string)))Difference from Redis CLI ↟
Since LFE is a fixed-arity language, a few differences exist between ledis and the Redis CLI. These usually are for the following scenarios:
- Optional command arguments which have been converted to LFE as options (using proplists).
- Some Redis commands conflict with LFE functions/macros, and these have been renamed.
- Some variable arity commands are converted to single-arity in LFE where the single argument is a list.
Functions which are different in these ways have been listed below with sample usage.
bitcount ↟
lfe> (ledis:bitcount 'foo)
#(ok #"10")
lfe> (ledis:bitcount 'foo '(#(start 2) #(end 4)))
#(ok #"4")bitop ↟
lfe> (ledis:set 'key1 "foobar")
#(ok #"OK")
lfe> (ledis:set 'key2 "absdef")
#(ok #"OK")
lfe> (ledis:bitop 'AND 'dest '(key1 key2))
#(ok #"6")
lfe> (ledis:get 'dest)
#(ok #"`bc`ab")bitpos ↟
lfe> (ledis:set 'mykey #b(#xff #xf0 #x00))
#(ok #"OK")
lfe> (ledis:bitpos 'mykey 0)
#(ok #"12")
lfe> (ledis:set 'mykey #b(#x00 #xff #xf0))
#(ok #"OK")
lfe> (ledis:bitpos 'mykey 1 '(#(start 1)))
#(ok #"8")
lfe> (ledis:bitpos 'mykey 1 '(#(start 2)))
#(ok #"16")
lfe> (ledis:set 'mykey #b(#x00 #x00 #x00))
#(ok #"OK")
lfe> (ledis:bitpos 'mykey 1)
#(ok #"-1")blpop ↟
The following would be returned if you had previously performed the (ledis:rpush 'list1 "banana" and (ledis:rpush 'list1 "tranbar") calls:
lfe> (ledis:blpop 'list1 0)
#(ok (#"list1" #"banana"))
lfe> (ledis:blpop '(list2 list3 list1) 0)
#(ok (#"list1" #"tranbar"))del ↟
lfe> (ledis:set 'mykey "Hello")
#(ok #"OK")
lfe> (ledis:del 'mykey)
#(ok #"1")
lfe> (ledis:multi-set '(key1 "val1" key2 "val2" key3 "val3"))
#(ok #"OK")
lfe> (ledis:del '(key1 key2 key3 key4))
#(ok #"3")hmset ↟
Normally, the HMSET Redis command is of the form
HMSET key field value [field value ...], but for simplicity's sake with
regard to LFE's arity, the hmset function is called a bit differently: It
is of the form (hmset <key> '(<kv pair> ...)). For instance:
lfe> (ledis:hmset 'foo2 '(field1 bar2))
#(ok #"OK")
lfe> (ledis:hmset 'foo2 '(field2 bizaz field3 boz field4 bleez))
#(ok #"OK")These can then be accessed using hmget:
lfe> (ledis:hmget 'foo2 'field4)
#(ok (#"bleez"))
lfe> (ledis:hmget 'foo2 '(field3 field2 field1))
#(ok (#"boz" #"bizaz" #"bar2"))lrange ↟
In addition to lrange/3 and lrange/4 (which offers the same signature as
associated Redis commands, with the 4-arity function also allowing options to be
passed), ledis offers two additional arities for this function. Arity-1 and
arity-2 will return the entire list at the given key (the following will be
returned if you have previously done something like (ledis:lpush-multi 'fruits '("banana" "tranbar" "kiwi") '())):
lfe> (ledis:lrange 'fruits)
#(ok
(#"banana"
#"tranbar"
#"kiwi"))M* renamed to multi-* ↟
lfe> (ledis:multi-set '(a 10 b 20 c 30))
#(ok #"OK")
lfe> (ledis:multi-get '(a b c))
#(ok (#"10" #"20" #"30"))set ↟
lfe> (ledis:set 'mykey "athirdvalue" '(#(xx) #(px 10000)))
#(ok #"OK")
lfe> (ledis:get 'mykey)
#(ok #"athirdvalue")
lfe> (timer:sleep 10000)
ok
lfe> (ledis:get 'mykey)
#(ok undefined)Notes for Developers ↟
You can run the meager integration tests with the following, if you have a local instance of Redis running:
$ rebar3 as test lfe ltest -tintegrationIf you have an interest in making contributions to this library, you'll need to make note of how the wrappring works.
- For every n-arity function you wish to add (wrap), you'll also need to add an n+1-arity function of the same name. This is because ledis supports (requires) a version of every function that takes LFE-specific options (e.g., setting return types).
- Under most circumstances, this just means making an entry in the functions
get-api-funcs-no-optsandget-api-funcs-with-optsin the fileinclude/ledis.lfe. - Non-normal circumstances include supporting Redis functions of mixed arity,
special options, and non-standard or irregular function arguments. In these
cases, you will often be able to make an entry in
get-api-funcs-no-opts, but have to then create a custom n+1-arity function insrc/ledis.lfe. Sometimes you won't be able to use either of the API-generating functions and macros, and will instead need to implement both the n-arity and n+1-arity functions insrc/ledis.lfe.
