fraggle 3.0.0 → 4.0.0.pre.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +81 -23
- data/example/getdir_all.rb +29 -0
- data/example/readme.rb +56 -0
- data/example/walk_all.rb +29 -0
- data/example/watch.rb +12 -0
- data/lib/fraggle.rb +3 -0
- data/lib/fraggle/client.rb +48 -14
- data/lib/fraggle/version.rb +1 -1
- data/test/fraggle_client_test.rb +7 -7
- metadata +17 -9
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
# Fraggle (
|
1
|
+
# Fraggle (v4.0.0.pre.1 is compatible with Doozer 0.6)
|
2
2
|
|
3
3
|
Fraggle currently is only a raw interface to Doozer 0.6.
|
4
|
-
Sugar for `WALK`, `GETDIR`, etc are to come in v3.0.0.
|
5
4
|
|
6
5
|
**An EventMachine based Doozer client**
|
7
6
|
|
@@ -11,31 +10,42 @@ Sugar for `WALK`, `GETDIR`, etc are to come in v3.0.0.
|
|
11
10
|
|
12
11
|
## Use
|
13
12
|
|
13
|
+
*Connecting to a cluster*
|
14
|
+
|
15
|
+
Use `Fraggle.connect`. It takes an optional [doozer uri][] (String). If no
|
16
|
+
parameters are given, it will use the DOOZER_URI` environment variable if
|
17
|
+
present, otherwise it will default to the uri containing the default doozer
|
18
|
+
addresses with IP 127.0.0.1 and ports 8046, 8041, 8042, 8043.
|
19
|
+
|
20
|
+
*simple example*
|
21
|
+
|
14
22
|
require 'rubygems'
|
15
23
|
require 'eventmachine'
|
16
24
|
require 'fraggle'
|
17
25
|
|
18
|
-
EM.
|
26
|
+
EM.run do
|
19
27
|
# In the event of a lost connection, fraggle will attempt
|
20
28
|
# other doozers until one accepts or it runs out of options; A NoAddrs
|
21
29
|
# exception will be raised if that later happens.
|
22
|
-
c = Fraggle.connect "doozerd://127.0.0.1:8046"
|
23
30
|
|
24
|
-
|
25
|
-
if e.ok?
|
26
|
-
e.value # => nil
|
27
|
-
e.rev # => 0
|
28
|
-
e.missing? # => true
|
29
|
-
else
|
30
|
-
e.err_code # => Fraggle::<CONST>
|
31
|
-
e.err_detail # => "bad path" or something
|
32
|
-
end
|
33
|
-
end
|
31
|
+
c = Fraggle.connect
|
34
32
|
|
35
33
|
c.rev do |v|
|
34
|
+
c.get(v.rev, "/foo") do |e|
|
35
|
+
p [:get, e]
|
36
|
+
if e.ok?
|
37
|
+
e.value # => nil
|
38
|
+
e.rev # => 0
|
39
|
+
e.missing? # => true
|
40
|
+
else
|
41
|
+
e.err_code # => nil
|
42
|
+
e.err_detail # => nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
36
46
|
## Obtain the current revision the store is at and watch from then on for
|
37
47
|
## any SET or DEL to /foo.
|
38
|
-
c.wait("/foo"
|
48
|
+
c.wait(v.rev, "/foo") do |e|
|
39
49
|
# The event has:
|
40
50
|
# ------------------------
|
41
51
|
e.err_code # => nil
|
@@ -45,11 +55,13 @@ Sugar for `WALK`, `GETDIR`, etc are to come in v3.0.0.
|
|
45
55
|
e.rev # => 123
|
46
56
|
e.set? # => true
|
47
57
|
e.del? # => false
|
58
|
+
|
59
|
+
p [:wait, e]
|
48
60
|
end
|
49
61
|
end
|
50
62
|
|
51
63
|
## Setting a key (this will trigger the watch above)
|
52
|
-
|
64
|
+
c.set(Fraggle::Clobber, "/foo", "zomg!") do |e|
|
53
65
|
# Success!
|
54
66
|
case e.err_code
|
55
67
|
when Fraggle::REV_MISMATCH
|
@@ -57,7 +69,7 @@ Sugar for `WALK`, `GETDIR`, etc are to come in v3.0.0.
|
|
57
69
|
when nil
|
58
70
|
# Success!
|
59
71
|
else
|
60
|
-
fail "something bad happened"
|
72
|
+
fail "something bad happened: " + e.inspect
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
@@ -70,17 +82,17 @@ the most up-to-date data. If you need to do multiple reads at certain
|
|
70
82
|
point in time for consistency, use the `rev` command.
|
71
83
|
|
72
84
|
c.rev do |v|
|
73
|
-
c.get("/a"
|
74
|
-
c.get("/b"
|
75
|
-
c.get("/c"
|
85
|
+
c.get(v.rev, "/a") { ... }
|
86
|
+
c.get(v.rev, "/b") { ... }
|
87
|
+
c.get(v.rev, "/c") { ... }
|
76
88
|
end
|
77
89
|
|
78
90
|
This also means you can go back in time or into the future!
|
79
91
|
|
80
92
|
# This will not yield until the data store is at revision 100,000
|
81
|
-
c.get("/a"
|
93
|
+
c.get(100_000, "/a") { ... }
|
82
94
|
|
83
|
-
NOTE: Doozer's data store is a persistent data structure. You can reference the
|
95
|
+
NOTE: Doozer's data store is a [persistent data structure][pd]. You can reference the
|
84
96
|
stores history as far back as it is configured to hold it. The default is
|
85
97
|
360,000 revisions. See [data model][] for more information.
|
86
98
|
|
@@ -103,11 +115,54 @@ stores history as far back as it is configured to hold it. The default is
|
|
103
115
|
You will have to handle these yourself because Fraggle cannot know whether or
|
104
116
|
not it's safe to retry on your behalf.
|
105
117
|
|
118
|
+
## Commands
|
119
|
+
|
120
|
+
Each command behaves according to the [proto spec][], respectively.
|
121
|
+
Their `blk`s are called with one parameter, a `Fraggle::Response`, when a response is
|
122
|
+
returned from the server.
|
123
|
+
|
124
|
+
`set(rev, path, value, &blk)`
|
125
|
+
|
126
|
+
`del(rev, path, &blk)`
|
127
|
+
|
128
|
+
`get(rev, path, &blk)`
|
129
|
+
|
130
|
+
`getdir(rev, path, offset, &blk)`
|
131
|
+
|
132
|
+
`walk(rev, path, offset, &blk)`
|
133
|
+
|
134
|
+
`wait(rev, path, &blk)`
|
135
|
+
|
136
|
+
`rev(&blk)`
|
137
|
+
|
138
|
+
`stat(rev, path, &blk)`
|
139
|
+
|
140
|
+
## Sugar commands
|
141
|
+
|
142
|
+
`watch(rev, path, &blk)`
|
143
|
+
|
144
|
+
Watches `path` (a glob pattern) for changes, from `rev` in history on. Its
|
145
|
+
`blk` is called with a `Fraggle::Response` for each event.
|
146
|
+
|
147
|
+
`getdir_all(rev, path, off=0, lim=MaxInt64, ents=[], &blk)`
|
148
|
+
|
149
|
+
Behaves like `getdir` but collects `ents`, starting at `off` until all or `lim`
|
150
|
+
entries are read. When done `blk` is called with the result as the first
|
151
|
+
parameter or an error as the second. Depending on the response, one or the
|
152
|
+
other will be set and the other with be `nil`.
|
153
|
+
|
154
|
+
`walk_all(rev, path, off=0, lim=MaxInt64, ents=[], &blk)`
|
155
|
+
|
156
|
+
Behaves like `walk` but collects `ents`, starting at `off` until all or `lim`
|
157
|
+
entries are read. When done `blk` is called with the result as the first
|
158
|
+
parameter or an error as the second. Depending on the response, one or the
|
159
|
+
other will be set and the other with be `nil`.
|
160
|
+
|
106
161
|
## Dev
|
107
162
|
|
108
163
|
**Clone**
|
109
164
|
|
110
|
-
$ git clone http://github.com/
|
165
|
+
$ git clone http://github.com/ha/fraggle.git
|
111
166
|
|
112
167
|
**Test**
|
113
168
|
|
@@ -121,3 +176,6 @@ Please join the Doozer mailing list for help:
|
|
121
176
|
http://groups.google.com/forum/#!forum/doozer
|
122
177
|
|
123
178
|
[data model]: https://github.com/ha/doozerd/blob/master/doc/data-model.md
|
179
|
+
[doozer uri]: https://github.com/ha/doozerd/blob/master/doc/uri.md
|
180
|
+
[proto spec]: https://github.com/ha/doozerd/blob/master/doc/proto.md
|
181
|
+
[pd]: http://en.wikipedia.org/wiki/Persistent_data_structure
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fraggle'
|
3
|
+
|
4
|
+
EM.run do
|
5
|
+
c = Fraggle.connect
|
6
|
+
|
7
|
+
c.rev do |v|
|
8
|
+
# Valid
|
9
|
+
req = c.getdir_all("/ctl/node", v.rev) do |ents, err|
|
10
|
+
if err
|
11
|
+
p [:err, err]
|
12
|
+
else
|
13
|
+
ents.each do |e|
|
14
|
+
puts File.join(req.path, e.path)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Limit 0 return nothing
|
20
|
+
c.getdir_all("/ctl/node", v.rev, 0, 0) do |ents, err|
|
21
|
+
p [:ret, ents, err]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Error
|
25
|
+
c.getdir_all("/nothere", v.rev) do |ents, err|
|
26
|
+
p [:ret, ents, err]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/example/readme.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'fraggle'
|
4
|
+
|
5
|
+
EM.run do
|
6
|
+
# In the event of a lost connection, fraggle will attempt
|
7
|
+
# other doozers until one accepts or it runs out of options; A NoAddrs
|
8
|
+
# exception will be raised if that later happens.
|
9
|
+
|
10
|
+
c = Fraggle.connect
|
11
|
+
|
12
|
+
c.rev do |v|
|
13
|
+
c.get(v.rev, "/foo") do |e|
|
14
|
+
p [:get, e]
|
15
|
+
if e.ok?
|
16
|
+
e.value # => nil
|
17
|
+
e.rev # => 0
|
18
|
+
e.missing? # => true
|
19
|
+
else
|
20
|
+
e.err_code # => nil
|
21
|
+
e.err_detail # => nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
## Obtain the current revision the store is at and watch from then on for
|
26
|
+
## any SET or DEL to /foo.
|
27
|
+
c.wait(v.rev, "/foo") do |e|
|
28
|
+
# The event has:
|
29
|
+
# ------------------------
|
30
|
+
e.err_code # => nil
|
31
|
+
e.err_detail # => nil
|
32
|
+
e.path # => "/foo"
|
33
|
+
e.value # => "zomg!"
|
34
|
+
e.rev # => 123
|
35
|
+
e.set? # => true
|
36
|
+
e.del? # => false
|
37
|
+
|
38
|
+
p [:wait, e]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
## Setting a key (this will trigger the watch above)
|
43
|
+
c.set(0, "/foo", "zomg!") do |e|
|
44
|
+
# Success!
|
45
|
+
case e.err_code
|
46
|
+
when Fraggle::REV_MISMATCH
|
47
|
+
p :not_it
|
48
|
+
when nil
|
49
|
+
# Success!
|
50
|
+
p :it
|
51
|
+
else
|
52
|
+
fail "something bad happened: " + e.inspect
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/example/walk_all.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fraggle'
|
3
|
+
|
4
|
+
EM.run do
|
5
|
+
c = Fraggle.connect
|
6
|
+
|
7
|
+
c.rev do |v|
|
8
|
+
# Valid
|
9
|
+
req = c.walk_all("/ctl/node/**", v.rev) do |ents, err|
|
10
|
+
if err
|
11
|
+
p [:err, err]
|
12
|
+
else
|
13
|
+
ents.each do |e|
|
14
|
+
puts File.join(req.path, e.path) + "=" + e.value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Limit 0 return nothing
|
20
|
+
c.walk_all("/ctl/node/**", v.rev, 0, 0) do |ents, err|
|
21
|
+
p [:ret, ents, err]
|
22
|
+
end
|
23
|
+
|
24
|
+
# Error
|
25
|
+
c.walk_all("/nothere", v.rev) do |ents, err|
|
26
|
+
p [:ret, ents, err]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/example/watch.rb
ADDED
data/lib/fraggle.rb
CHANGED
data/lib/fraggle/client.rb
CHANGED
@@ -6,6 +6,8 @@ module Fraggle
|
|
6
6
|
class Client
|
7
7
|
include Request::Verb
|
8
8
|
|
9
|
+
MaxInt64 = 1<<63 - 1
|
10
|
+
|
9
11
|
class NoMoreAddrs < StandardError
|
10
12
|
end
|
11
13
|
|
@@ -22,7 +24,7 @@ module Fraggle
|
|
22
24
|
cn.addr
|
23
25
|
end
|
24
26
|
|
25
|
-
def set(path, value,
|
27
|
+
def set(rev, path, value, &blk)
|
26
28
|
req = Request.new
|
27
29
|
req.verb = SET
|
28
30
|
req.rev = rev
|
@@ -32,7 +34,7 @@ module Fraggle
|
|
32
34
|
idemp(req, &blk)
|
33
35
|
end
|
34
36
|
|
35
|
-
def get(
|
37
|
+
def get(rev, path, &blk)
|
36
38
|
req = Request.new
|
37
39
|
req.verb = GET
|
38
40
|
req.rev = rev
|
@@ -41,7 +43,7 @@ module Fraggle
|
|
41
43
|
resend(req, &blk)
|
42
44
|
end
|
43
45
|
|
44
|
-
def del(
|
46
|
+
def del(rev, path, &blk)
|
45
47
|
req = Request.new
|
46
48
|
req.verb = DEL
|
47
49
|
req.rev = rev
|
@@ -50,7 +52,7 @@ module Fraggle
|
|
50
52
|
idemp(req, &blk)
|
51
53
|
end
|
52
54
|
|
53
|
-
def getdir(
|
55
|
+
def getdir(rev, path, offset, &blk)
|
54
56
|
req = Request.new
|
55
57
|
req.verb = GETDIR
|
56
58
|
req.rev = rev
|
@@ -60,7 +62,7 @@ module Fraggle
|
|
60
62
|
resend(req, &blk)
|
61
63
|
end
|
62
64
|
|
63
|
-
def walk(
|
65
|
+
def walk(rev, path, offset, &blk)
|
64
66
|
req = Request.new
|
65
67
|
req.verb = WALK
|
66
68
|
req.rev = rev
|
@@ -70,7 +72,7 @@ module Fraggle
|
|
70
72
|
resend(req, &blk)
|
71
73
|
end
|
72
74
|
|
73
|
-
def wait(
|
75
|
+
def wait(rev, path, &blk)
|
74
76
|
req = Request.new
|
75
77
|
req.verb = WAIT
|
76
78
|
req.rev = rev
|
@@ -86,7 +88,7 @@ module Fraggle
|
|
86
88
|
resend(req, &blk)
|
87
89
|
end
|
88
90
|
|
89
|
-
def stat(
|
91
|
+
def stat(rev, path, &blk)
|
90
92
|
req = Request.new
|
91
93
|
req.rev = rev
|
92
94
|
req.verb = STAT
|
@@ -95,19 +97,51 @@ module Fraggle
|
|
95
97
|
resend(req, &blk)
|
96
98
|
end
|
97
99
|
|
100
|
+
def watch(rev, path, &blk)
|
101
|
+
wait(rev, path, rev) do |e|
|
102
|
+
blk.call(e)
|
103
|
+
if e.ok?
|
104
|
+
watch(rev, path, e.rev+1, &blk)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def getdir_all(rev, path, off=0, lim=MaxInt64, ents=[], &blk)
|
110
|
+
all(:getdir, rev, path, off, lim, ents, &blk)
|
111
|
+
end
|
112
|
+
|
113
|
+
def walk_all(rev, path, off=0, lim=MaxInt64, ents=[], &blk)
|
114
|
+
all(:walk, rev, path, off, lim, ents, &blk)
|
115
|
+
end
|
116
|
+
|
117
|
+
def all(m, rev, path, off, lim, ents=[], &blk)
|
118
|
+
if lim == 0
|
119
|
+
cn.next_tick { blk.call([], nil) }
|
120
|
+
return
|
121
|
+
end
|
122
|
+
|
123
|
+
__send__(m, rev, path, off) do |e|
|
124
|
+
case e.err_code
|
125
|
+
when nil
|
126
|
+
ents << e
|
127
|
+
all(m, rev, path, off+1, lim-1, ents, &blk)
|
128
|
+
when Fraggle::Response::Err::RANGE
|
129
|
+
blk.call(ents, nil)
|
130
|
+
else
|
131
|
+
blk.call(nil, e)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
98
136
|
# Sends a request to the server. Returns the request with a new tag
|
99
137
|
# assigned.
|
100
138
|
def send(req, &blk)
|
101
139
|
cb = Proc.new do |e|
|
102
140
|
log.debug("response: #{e.inspect} for #{req.inspect}")
|
103
141
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
if cn.err?
|
108
|
-
log.error("conn err: #{req.inspect}")
|
109
|
-
reconnect!
|
110
|
-
end
|
142
|
+
if e.disconnected? && cn.err?
|
143
|
+
log.error("conn err: #{req.inspect}")
|
144
|
+
reconnect!
|
111
145
|
end
|
112
146
|
|
113
147
|
blk.call(e)
|
data/lib/fraggle/version.rb
CHANGED
data/test/fraggle_client_test.rb
CHANGED
@@ -150,7 +150,7 @@ class FraggleClientTest < Test::Unit::TestCase
|
|
150
150
|
:value => "bar"
|
151
151
|
}
|
152
152
|
|
153
|
-
assert_verb exp, :set, "/foo", "bar"
|
153
|
+
assert_verb exp, :set, 0, "/foo", "bar"
|
154
154
|
end
|
155
155
|
|
156
156
|
def test_get
|
@@ -160,7 +160,7 @@ class FraggleClientTest < Test::Unit::TestCase
|
|
160
160
|
:path => "/foo"
|
161
161
|
}
|
162
162
|
|
163
|
-
assert_verb exp, :get, "/foo"
|
163
|
+
assert_verb exp, :get, 0, "/foo"
|
164
164
|
end
|
165
165
|
|
166
166
|
def test_del
|
@@ -170,7 +170,7 @@ class FraggleClientTest < Test::Unit::TestCase
|
|
170
170
|
:path => "/foo"
|
171
171
|
}
|
172
172
|
|
173
|
-
assert_verb exp, :del, "/foo"
|
173
|
+
assert_verb exp, :del, 0, "/foo"
|
174
174
|
end
|
175
175
|
|
176
176
|
def test_getdir
|
@@ -181,7 +181,7 @@ class FraggleClientTest < Test::Unit::TestCase
|
|
181
181
|
:offset => 0
|
182
182
|
}
|
183
183
|
|
184
|
-
assert_verb exp, :getdir, "/foo", 0
|
184
|
+
assert_verb exp, :getdir, 0, "/foo", 0
|
185
185
|
end
|
186
186
|
|
187
187
|
def test_rev
|
@@ -199,7 +199,7 @@ class FraggleClientTest < Test::Unit::TestCase
|
|
199
199
|
:path => "/foo"
|
200
200
|
}
|
201
201
|
|
202
|
-
assert_verb exp, :stat, "/foo"
|
202
|
+
assert_verb exp, :stat, 0, "/foo"
|
203
203
|
end
|
204
204
|
|
205
205
|
def test_walk
|
@@ -210,7 +210,7 @@ class FraggleClientTest < Test::Unit::TestCase
|
|
210
210
|
:offset => 0
|
211
211
|
}
|
212
212
|
|
213
|
-
assert_verb exp, :walk, "/foo/*", 0
|
213
|
+
assert_verb exp, :walk, 0, "/foo/*", 0
|
214
214
|
end
|
215
215
|
|
216
216
|
def test_wait
|
@@ -220,7 +220,7 @@ class FraggleClientTest < Test::Unit::TestCase
|
|
220
220
|
:path => "/foo/*"
|
221
221
|
}
|
222
222
|
|
223
|
-
assert_verb exp, :wait, "/foo/*"
|
223
|
+
assert_verb exp, :wait, 0, "/foo/*"
|
224
224
|
end
|
225
225
|
|
226
226
|
end
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fraggle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 1923831851
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
|
-
-
|
7
|
+
- 4
|
8
8
|
- 0
|
9
9
|
- 0
|
10
|
-
|
10
|
+
- pre
|
11
|
+
- 1
|
12
|
+
version: 4.0.0.pre.1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Blake Mizerany
|
@@ -15,7 +17,7 @@ autorequire:
|
|
15
17
|
bindir: bin
|
16
18
|
cert_chain: []
|
17
19
|
|
18
|
-
date: 2011-
|
20
|
+
date: 2011-05-02 00:00:00 -07:00
|
19
21
|
default_executable:
|
20
22
|
dependencies:
|
21
23
|
- !ruby/object:Gem::Dependency
|
@@ -77,6 +79,10 @@ files:
|
|
77
79
|
- README.md
|
78
80
|
- Rakefile
|
79
81
|
- bench/gets.rb
|
82
|
+
- example/getdir_all.rb
|
83
|
+
- example/readme.rb
|
84
|
+
- example/walk_all.rb
|
85
|
+
- example/watch.rb
|
80
86
|
- fraggle.gemspec
|
81
87
|
- lib/fraggle.rb
|
82
88
|
- lib/fraggle/client.rb
|
@@ -110,12 +116,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
110
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
117
|
none: false
|
112
118
|
requirements:
|
113
|
-
- - "
|
119
|
+
- - ">"
|
114
120
|
- !ruby/object:Gem::Version
|
115
|
-
hash:
|
121
|
+
hash: 25
|
116
122
|
segments:
|
117
|
-
-
|
118
|
-
|
123
|
+
- 1
|
124
|
+
- 3
|
125
|
+
- 1
|
126
|
+
version: 1.3.1
|
119
127
|
requirements: []
|
120
128
|
|
121
129
|
rubyforge_project: fraggle
|