Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

pipelined erlang redis client

branch: master

Making redo.erl's state self updating

The last stable version is v1.1.0, in its own branch. However, moving
from that branch to the current master in production cases may break
due to the internal tuple change, and that not all redo users have it
under supervision, the update should ideally be done internally.

This patch adds internal checks for the State argument and calls for an
update if it detects the old form from v1.1.0 and updates it to the
current form, setting the reconnection argument to 'true'.
latest commit 7c7eaef4cd
Fred Hebert ferd authored March 25, 2013
Octocat-spinner-32 src Making redo.erl's state self updating March 25, 2013
Octocat-spinner-32 test
Octocat-spinner-32 .gitignore correcting behavior parsing empty strings April 21, 2011
Octocat-spinner-32 Makefile initial commit April 20, 2011
Octocat-spinner-32 README.md
Octocat-spinner-32 rebar initial commit April 20, 2011
README.md

Philosophy

If you wish to write a redis client from scratch, you must first invent the universe.

About

Redo is a pipelined redis client written in Erlang. It lacks any sort of syntactic sugar. The only API function is redo:cmd, which takes a raw redis command.

Build

$ make

Test

Unit tests

$ ./rebar eunit suite=redo

Local read benchmark

$ erl -pa ebin
1> bench:sync(1000).
91ms
10989 req/sec

2> bench:async(1000, 100).
38ms
26315 req/sec

Concurrency test

$ erl -pa ebin
1> redo_concurrency_test:run(20, 100). %% 20 pids, 100 random operations performed per pid

Start

No arguments: register process as "redo"

$ erl -pa ebin
1> redo:start_link().
{ok, <0.33.0>
2> whereis(redo).
<0.33.0>
3> redo:cmd(["PING"]).  
<<"PONG">>

Register with custom name

erl -pa ebin
1> redo:start_link(myclient).
{ok,<0.33.0>}
2> whereis(myclient).
<0.33.0>
8> redo:cmd(myclient, ["PING"]).  
<<"PONG">>

Start anonymous Redo process

erl -pa ebin
1> {ok, Pid} = redo:start_link(undefined).
{ok,<0.33.0>}
2> redo:cmd(Pid, ["PING"]).
<<"PONG">>

Specifying connection options

erl -pa ebin
1> redo:start_link([{host, "localhost"}, {port, 6379}]).
{ok,<0.33.0>}
2> redo:cmd(["PING"]).
<<"PONG">>

3> redo:start_link(myclient, [{host, "localhost"}, {port, 6379}]).
{ok,<0.37.0>}
4> redo:cmd(myclient, ["PING"]).
<<"PONG">>

Commands

erl -pa ebin
1> redo:start_link().
<0.33.0>
2> redo:cmd(["SET", "foo"]).
{error,<<"ERR wrong number of arguments for 'set' command">>}
3> redo:cmd(["SET", "foo", "bar"]).
<<"OK">>
4> redo:cmd(["GET", "foo"]).
<<"bar">>
5> redo:cmd(["HMSET", "hfoo", "ONE", "ABC", "TWO", "DEF"]).
<<"OK">>
6> redo:cmd(["HGETALL", "hfoo"]).
[<<"ONE">>,<<"ABC">>,<<"TWO">>,<<"DEF">>]

Pipelined commands

1> redo:start_link().
<0.33.>
2> redo:cmd([["GET", "foo"], ["HGETALL", "hfoo"]]).
[<<"bar">>, [<<"ONE">>,<<"ABC">>,<<"TWO">>,<<"DEF">>]]

Pub/Sub

$ erl -pa ebin
1> redo:start_link().
{ok,<0.33.0>}
2> Ref = redo:subscribe("chfoo").
#Ref<0.0.0.42>
3> (fun() -> receive {Ref, Res} -> Res after 10000 -> timeout end end)().
[<<"subscribe">>,<<"chfoo">>,1]
4> redo:start_link(client).  
{ok,<0.39.0>}
5> redo:cmd(client, ["PUBLISH", "chfoo", "hello"]).
1
6> (fun() -> receive {Ref, Res} -> Res after 10000 -> timeout end end)().
[<<"message">>,<<"chfoo">>,<<"hello">>]

%% restart redis server...

7> (fun() -> receive {Ref, Res} -> Res after 10000 -> timeout end end)().
closed
8> f(Ref).
ok
9> Ref = redo:subscribe("chfoo").                                        
#Ref<0.0.0.68>
10> (fun() -> receive {Ref, Res} -> Res after 10000 -> timeout end end)().
[<<"subscribe">>,<<"chfoo">>,1]
11> redo:cmd(client, ["PUBLISH", "chfoo", "hello again"]).
1
12> (fun() -> receive {Ref, Res} -> Res after 10000 -> timeout end end)().
[<<"message">>,<<"chfoo">>,<<"hello again">>]
Something went wrong with that request. Please try again.