Fraggle (v1.0.0.pre.2 is compatable with Doozer 0.5)
An EventMachine based Doozer client
Install
$ gem install fraggle --pre
Use
require 'rubygems'
require 'eventmachine'
require 'fraggle'
EM.start do
# Fraggle keeps track of this addr plus all others it finds once
# connected. In the event of a lost connection, fraggle will attempt
# other doozers until one accepts or it runs out of options; A NoAddrs
# exception will be raised if that later happens.
c = Fraggle.connect "doozerd://127.0.0.1:8046"
req = c.get("/foo") do |e|
e.value # => "bar"
e.rev # => 123
end
req.error do |e|
e.err_code # => nil
e.err_detail # => nil
end
watch = c.watch("/foo") do |e|
# The event has:
# ------------------------
e.err_code # => nil
e.err_detail # => nil
e.path # => "/foo"
e.value # => "bar"
e.rev # => 123
e.set? # => true
e.del? # => false
do_something_with(e)
# Phoney check for example
if can_stop_watching?(path)
watch.cancel
end
end
## Setting a key (this will trigger the watch above)
req = c.set("/foo", "zomg!", 0) do |e|
# Success!
end.error do |e|
if e.mismatch?
# There was a rev mismatch, handle this.
else
raise e.err_detail
end
end
# Knowning when a command is done is useful in some cases.
# Use the `done` callback for those situations.
ents = []
c.getdir("/test") do |e|
ents << e
end.done do
p ents
end
c.get("/nothere") do |e|
e.missing? # => true
end
end
Consistency
Fraggle read commands take a rev
. If no rev is given, Doozer will reply with
the most up-to-date data. If you need to do multiple reads at certain
point in time for consistency, use the rev
command.
c.rev do |v|
c.get("/a", v.rev) { ... }
c.get("/b", v.rev) { ... }
c.get("/c", v.rev) { ... }
end
This also means you can go back in time or into the future!
# This will not yield until the data store is at revision 100,000
c.get("/a", 100_000) { ... }
High Availability
Fraggle has mechanisms to gracefully deal with connection loss. They are:
Monitoring cluster activity
Fraggle monitors new Doozer nodes that come and go. This enables Fraggle to keep an up-to-date list of available nodes it can connect to in the case of a connection loss.
Resend / Connection loss
When a connection is lost and Fraggle successfully reconnects to another
Doozer node, Fraggle will resend most pending requests to the new connection.
This means you will not miss events; Even events that happened while you were
disconnected! All read commands will pick up where they left off. This is
valuable to understand because it means you don't need to code for failure on
reads; Fraggle gracefully handles it for you. This is really important for
the WATCH
command.
Write commands will be resent if their rev
is greater than 0. These are
idempotent requests. A rev of 0 or less will cause that request's error
callback to be invoked with a Fraggle::Connection::Disconnected response.
You will have to handle these yourself because Fraggle cannot know whether or
not it's safe to retry on your behalf.
For commands with multiple responses (i.e. walk
, watch
, getdir
), Fraggle
will update their offset and limit as each response comes in. This means
if you disconnect in the middle of the responses, Fraggle will gracefully
resend the requests making it appear nothing happened and continue giving you
the remaining responses.
Dev
Clone
$ git clone http://github.com/bmizerany/fraggle.git
Test
$ gem install turn
$ turn