fraggle 4.0.0.pre.1 → 4.0.0.pre.2

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/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ *.prof*
data/README.md CHANGED
@@ -1,11 +1,14 @@
1
- # Fraggle (v4.0.0.pre.1 is compatible with Doozer 0.6)
1
+ # Fraggle
2
+ ## The current gem is v4.0.0.pre.1 is compatible with Doozer 0.6
2
3
 
3
- Fraggle currently is only a raw interface to Doozer 0.6.
4
+ Please see the [4.0.0.pre.1 README](https://github.com/ha/fraggle/tree/v4.0.0.pre.1) for instructions on use.
4
5
 
5
6
  **An EventMachine based Doozer client**
6
7
 
7
8
  ## Install
8
9
 
10
+ (For pre-releases, use `--pre`)
11
+
9
12
  $ gem install fraggle
10
13
 
11
14
  ## Use
@@ -31,48 +34,75 @@ addresses with IP 127.0.0.1 and ports 8046, 8041, 8042, 8043.
31
34
  c = Fraggle.connect
32
35
 
33
36
  c.rev do |v|
34
- c.get(v.rev, "/foo") do |e|
35
- p [:get, e]
36
- if e.ok?
37
+ c.get(v, "/foo") do |e, err|
38
+ if err
39
+ err.code # => nil
40
+ err.detail # => nil
41
+ else
37
42
  e.value # => nil
38
43
  e.rev # => 0
39
44
  e.missing? # => true
40
- else
41
- e.err_code # => nil
42
- e.err_detail # => nil
43
45
  end
46
+
47
+ p [:get, e, err]
44
48
  end
45
49
 
46
50
  ## Obtain the current revision the store is at and watch from then on for
47
51
  ## any SET or DEL to /foo.
48
- c.wait(v.rev, "/foo") do |e|
52
+ c.wait(v, "/foo") do |e, err|
49
53
  # The event has:
50
54
  # ------------------------
51
- e.err_code # => nil
52
- e.err_detail # => nil
53
- e.path # => "/foo"
54
- e.value # => "zomg!"
55
- e.rev # => 123
56
- e.set? # => true
57
- e.del? # => false
58
-
59
- p [:wait, e]
55
+ if err
56
+ err.code # => nil
57
+ err.detail # => nil
58
+ else
59
+ e.path # => "/foo"
60
+ e.value # => "zomg!"
61
+ e.rev # => 123
62
+ e.set? # => true
63
+ e.del? # => false
64
+ end
65
+
66
+ p [:wait, e, err]
60
67
  end
61
68
  end
62
69
 
63
70
  ## Setting a key (this will trigger the watch above)
64
- c.set(Fraggle::Clobber, "/foo", "zomg!") do |e|
71
+ f = Proc.new do |e, err|
72
+ p [:e, e, err]
73
+
74
+ if err && err.disconnected?
75
+ # Fraggle (for now) does not attempt a non-idempotent request. This means
76
+ # Fraggle will hand off the error to the user if there is a SET or DEL
77
+ # with rev 0 (missing) and delete it during the time we may be
78
+ # disconnected.
79
+ #
80
+ # In this scenario, there are no other clients that can exist that will
81
+ # attempt to set this "lock" if it's missing then delete it. It is safe
82
+ # for us to resend the request if we were disconnected from the previous
83
+ # server before a response.
84
+ #
85
+ # See High-Availability in the README for more information about this.
86
+ #
87
+ c.set(0, "/foo", "zomg!", &f)
88
+ next
89
+ end
90
+
65
91
  # Success!
66
- case e.err_code
67
- when Fraggle::REV_MISMATCH
68
- # We didn't win
69
- when nil
70
- # Success!
71
- else
72
- fail "something bad happened: " + e.inspect
92
+ if err
93
+ case err.code
94
+ when Fraggle::REV_MISMATCH
95
+ p :not_it
96
+ when nil
97
+ # Success!
98
+ p [:it, e]
99
+ else
100
+ fail "something bad happened: " + e.inspect
101
+ end
73
102
  end
74
103
  end
75
104
 
105
+ c.set(0, "/foo", "zomg!", &f)
76
106
  end
77
107
 
78
108
  ## Consistency
@@ -82,9 +112,9 @@ the most up-to-date data. If you need to do multiple reads at certain
82
112
  point in time for consistency, use the `rev` command.
83
113
 
84
114
  c.rev do |v|
85
- c.get(v.rev, "/a") { ... }
86
- c.get(v.rev, "/b") { ... }
87
- c.get(v.rev, "/c") { ... }
115
+ c.get(v, "/a") { ... }
116
+ c.get(v, "/b") { ... }
117
+ c.get(v, "/c") { ... }
88
118
  end
89
119
 
90
120
  This also means you can go back in time or into the future!
@@ -117,8 +147,9 @@ stores history as far back as it is configured to hold it. The default is
117
147
 
118
148
  ## Commands
119
149
 
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
150
+ Each command below behaves according to the [proto spec][], respectively.
151
+ Their `blk`s are called with two parameters, a `Fraggle::Response` as the first
152
+ or a `Fraggle::Connection::ResponseError` as the second if a response is
122
153
  returned from the server.
123
154
 
124
155
  `set(rev, path, value, &blk)`
@@ -127,10 +158,6 @@ returned from the server.
127
158
 
128
159
  `get(rev, path, &blk)`
129
160
 
130
- `getdir(rev, path, offset, &blk)`
131
-
132
- `walk(rev, path, offset, &blk)`
133
-
134
161
  `wait(rev, path, &blk)`
135
162
 
136
163
  `rev(&blk)`
@@ -144,19 +171,17 @@ returned from the server.
144
171
  Watches `path` (a glob pattern) for changes, from `rev` in history on. Its
145
172
  `blk` is called with a `Fraggle::Response` for each event.
146
173
 
147
- `getdir_all(rev, path, off=0, lim=MaxInt64, ents=[], &blk)`
174
+ `getdir(rev, path, off=0, lim=MaxInt64, ents=[], &blk)`
148
175
 
149
176
  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`.
177
+ entries are read. When done, `blk` is called with the result (an `Array`) as the
178
+ first parameter or a `Fraggle::Connection::Response` as the second. Depending
179
+ on the response, one or the other will be set and the other with be `nil`.
153
180
 
154
- `walk_all(rev, path, off=0, lim=MaxInt64, ents=[], &blk)`
181
+ `walk(rev, path, off=0, lim=MaxInt64, ents=[], &blk)`
155
182
 
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`.
183
+ Like `getdir`, but but path is a glob pattern and each result contains a `path`,
184
+ `value`, and `rev`.
160
185
 
161
186
  ## Dev
162
187
 
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # By Mark McGranaghan
4
+
5
+ require "rubygems"
6
+ require "bundler"
7
+ Bundler.setup
8
+ require "fraggle"
9
+ require "statsample"
10
+
11
+ $stdout.sync = true
12
+
13
+ abort("read <[get|set]> <total> <width> [verbose]") if (ARGV.size < 2)
14
+ op = ARGV.shift.to_sym
15
+ total = ARGV.shift.to_i
16
+ width = ARGV.shift.to_i
17
+ verbose = !!ARGV.shift
18
+ latencies = []
19
+ sent_at = nil
20
+
21
+ EM.run do
22
+ client = Fraggle.connect
23
+ sent = 0
24
+ received = 0
25
+ start = Time.now
26
+
27
+ f = Proc.new do |r|
28
+ received_at = Time.now
29
+ received +=1
30
+ latency = received_at - sent_at
31
+
32
+ latencies << latency
33
+ if verbose
34
+ $stdout.puts("received=#{received} ok=#{r.ok?} rev=#{r.rev} latency=#{latency}")
35
+ elsif (received % 10 == 0)
36
+ $stdout.print(".")
37
+ end
38
+ if (received == total)
39
+ EM.stop
40
+ elapsed = Time.now - start
41
+ vector = latencies.to_scale
42
+ $stdout.puts
43
+ $stdout.puts("total=#{total}")
44
+ $stdout.puts("elapsed=#{elapsed}")
45
+ $stdout.puts("rate=#{total / elapsed}")
46
+ $stdout.puts("mean=#{vector.mean}")
47
+ $stdout.puts("sd=#{vector.sd}")
48
+ $stdout.puts("perc90=#{vector.percentil(90)}")
49
+ $stdout.puts("perc99=#{vector.percentil(99)}")
50
+ $stdout.puts("max=#{vector.max}")
51
+ end
52
+ end
53
+
54
+ tick = Proc.new do
55
+ if (sent == total)
56
+ # done sending
57
+ elsif ((sent - received) < width)
58
+ # pipe open
59
+ sent_at = Time.now
60
+ sent += 1
61
+ if verbose
62
+ $stdout.puts("sent=#{sent}")
63
+ end
64
+
65
+ case op
66
+ when :get
67
+ client.get(nil, "/processes/#{sent}", &f)
68
+ when :set
69
+ client.set(Fraggle::Clobber, "/processes/#{sent}", "1", &f)
70
+ end
71
+ else
72
+ # pipe closed
73
+ end
74
+ EM.next_tick(&tick)
75
+ end
76
+ tick.call
77
+ end
@@ -6,7 +6,7 @@ EM.run do
6
6
 
7
7
  c.rev do |v|
8
8
  # Valid
9
- req = c.getdir_all("/ctl/node", v.rev) do |ents, err|
9
+ req = c.getdir(v, "/ctl/node") do |ents, err|
10
10
  if err
11
11
  p [:err, err]
12
12
  else
@@ -17,12 +17,12 @@ EM.run do
17
17
  end
18
18
 
19
19
  # Limit 0 return nothing
20
- c.getdir_all("/ctl/node", v.rev, 0, 0) do |ents, err|
20
+ c.getdir(v, "/ctl/node", 0, 0) do |ents, err|
21
21
  p [:ret, ents, err]
22
22
  end
23
23
 
24
24
  # Error
25
- c.getdir_all("/nothere", v.rev) do |ents, err|
25
+ c.getdir(v, "/nothere") do |ents, err|
26
26
  p [:ret, ents, err]
27
27
  end
28
28
  end
@@ -10,47 +10,73 @@ EM.run do
10
10
  c = Fraggle.connect
11
11
 
12
12
  c.rev do |v|
13
- c.get(v.rev, "/foo") do |e|
14
- p [:get, e]
15
- if e.ok?
13
+ c.get(v, "/foo") do |e, err|
14
+ if err
15
+ err.code # => nil
16
+ err.detail # => nil
17
+ else
16
18
  e.value # => nil
17
19
  e.rev # => 0
18
20
  e.missing? # => true
19
- else
20
- e.err_code # => nil
21
- e.err_detail # => nil
22
21
  end
22
+
23
+ p [:get, e, err]
23
24
  end
24
25
 
25
26
  ## Obtain the current revision the store is at and watch from then on for
26
27
  ## any SET or DEL to /foo.
27
- c.wait(v.rev, "/foo") do |e|
28
+ c.wait(v, "/foo") do |e, err|
28
29
  # The event has:
29
30
  # ------------------------
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]
31
+ if err
32
+ err.code # => nil
33
+ err.detail # => nil
34
+ else
35
+ e.path # => "/foo"
36
+ e.value # => "zomg!"
37
+ e.rev # => 123
38
+ e.set? # => true
39
+ e.del? # => false
40
+ end
41
+
42
+ p [:wait, e, err]
39
43
  end
40
44
  end
41
45
 
42
46
  ## Setting a key (this will trigger the watch above)
43
- c.set(0, "/foo", "zomg!") do |e|
47
+ f = Proc.new do |e, err|
48
+ p [:e, e, err]
49
+
50
+ if err && err.disconnected?
51
+ # Fraggle (for now) does not attempt a non-idempotent request. This means
52
+ # Fraggle will hand off the error to the user if there is a SET or DEL
53
+ # with rev 0 (missing) and delete it during the time we may be
54
+ # disconnected.
55
+ #
56
+ # In this scenario, there are no other clients that can exist that will
57
+ # attempt to set this "lock" if it's missing then delete it. It is safe
58
+ # for us to resend the request if we were disconnected from the previous
59
+ # server before a response.
60
+ #
61
+ # See High-Availability in the README for more information about this.
62
+ #
63
+ c.set(0, "/foo", "zomg!", &f)
64
+ next
65
+ end
66
+
44
67
  # 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
68
+ if err
69
+ case err.code
70
+ when Fraggle::REV_MISMATCH
71
+ p :not_it
72
+ when nil
73
+ # Success!
74
+ p [:it, e]
75
+ else
76
+ fail "something bad happened: " + e.inspect
77
+ end
53
78
  end
54
79
  end
55
80
 
81
+ c.set(0, "/foo", "zomg!", &f)
56
82
  end
@@ -6,7 +6,7 @@ EM.run do
6
6
 
7
7
  c.rev do |v|
8
8
  # Valid
9
- req = c.walk_all("/ctl/node/**", v.rev) do |ents, err|
9
+ req = c.walk(v, "/ctl/node/**") do |ents, err|
10
10
  if err
11
11
  p [:err, err]
12
12
  else
@@ -17,13 +17,13 @@ EM.run do
17
17
  end
18
18
 
19
19
  # Limit 0 return nothing
20
- c.walk_all("/ctl/node/**", v.rev, 0, 0) do |ents, err|
21
- p [:ret, ents, err]
20
+ c.walk(v, "/ctl/node/**", 0, 0) do |ents, err|
21
+ p [:nothing, ents, err]
22
22
  end
23
23
 
24
24
  # Error
25
- c.walk_all("/nothere", v.rev) do |ents, err|
26
- p [:ret, ents, err]
25
+ c.walk(v, "/nothere") do |ents, err|
26
+ p [:nothere, ents, err]
27
27
  end
28
28
  end
29
29
  end
@@ -5,8 +5,8 @@ EM.run do
5
5
  c = Fraggle.connect
6
6
 
7
7
  c.rev do |v|
8
- c.watch("/ctl/node/**", v.rev) do |e|
9
- p e
8
+ c.watch(v, "/ctl/node/**") do |e, err|
9
+ p [e, err]
10
10
  end
11
11
  end
12
12
  end
@@ -23,4 +23,5 @@ Gem::Specification.new do |s|
23
23
  s.add_dependency "eventmachine"
24
24
 
25
25
  s.add_development_dependency "turn"
26
+ s.add_development_dependency "statsample"
26
27
  end
@@ -1,6 +1,5 @@
1
1
  require 'eventmachine'
2
2
  require 'fraggle/connection'
3
- require 'logger'
4
3
 
5
4
  module Fraggle
6
5
  class Client
@@ -11,13 +10,10 @@ module Fraggle
11
10
  class NoMoreAddrs < StandardError
12
11
  end
13
12
 
14
- DefaultLog = Logger.new(STDERR)
15
- DefaultLog.level = Logger::UNKNOWN
13
+ attr_reader :cn, :addrs
16
14
 
17
- attr_reader :cn, :log, :addrs
18
-
19
- def initialize(cn, addrs, log=DefaultLog)
20
- @cn, @addrs, @log = cn, addrs, log
15
+ def initialize(cn, addrs)
16
+ @cn, @addrs = cn, addrs
21
17
  end
22
18
 
23
19
  def addr
@@ -52,7 +48,7 @@ module Fraggle
52
48
  idemp(req, &blk)
53
49
  end
54
50
 
55
- def getdir(rev, path, offset, &blk)
51
+ def _getdir(rev, path, offset, &blk)
56
52
  req = Request.new
57
53
  req.verb = GETDIR
58
54
  req.rev = rev
@@ -62,7 +58,7 @@ module Fraggle
62
58
  resend(req, &blk)
63
59
  end
64
60
 
65
- def walk(rev, path, offset, &blk)
61
+ def _walk(rev, path, offset, &blk)
66
62
  req = Request.new
67
63
  req.verb = WALK
68
64
  req.rev = rev
@@ -85,7 +81,9 @@ module Fraggle
85
81
  req = Request.new
86
82
  req.verb = REV
87
83
 
88
- resend(req, &blk)
84
+ resend(req) do |v, _|
85
+ blk.call(v.rev)
86
+ end
89
87
  end
90
88
 
91
89
  def stat(rev, path, &blk)
@@ -97,21 +95,29 @@ module Fraggle
97
95
  resend(req, &blk)
98
96
  end
99
97
 
98
+ def access(secret, &blk)
99
+ req = Request.new
100
+ req.verb = ACCESS
101
+ req.value = secret
102
+
103
+ resend(req, &blk)
104
+ end
105
+
100
106
  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)
107
+ wait(rev, path) do |e, err|
108
+ blk.call(e, err)
109
+ if ! err
110
+ watch(e.rev+1, path, &blk)
105
111
  end
106
112
  end
107
113
  end
108
114
 
109
- def getdir_all(rev, path, off=0, lim=MaxInt64, ents=[], &blk)
110
- all(:getdir, rev, path, off, lim, ents, &blk)
115
+ def getdir(rev, path, off=0, lim=MaxInt64, ents=[], &blk)
116
+ all(:_getdir, rev, path, off, lim, ents, &blk)
111
117
  end
112
118
 
113
- def walk_all(rev, path, off=0, lim=MaxInt64, ents=[], &blk)
114
- all(:walk, rev, path, off, lim, ents, &blk)
119
+ def walk(rev, path, off=0, lim=MaxInt64, ents=[], &blk)
120
+ all(:_walk, rev, path, off, lim, ents, &blk)
115
121
  end
116
122
 
117
123
  def all(m, rev, path, off, lim, ents=[], &blk)
@@ -120,11 +126,10 @@ module Fraggle
120
126
  return
121
127
  end
122
128
 
123
- __send__(m, rev, path, off) do |e|
124
- case e.err_code
129
+ __send__(m, rev, path, off) do |e, err|
130
+ case err && err.code
125
131
  when nil
126
- ents << e
127
- all(m, rev, path, off+1, lim-1, ents, &blk)
132
+ all(m, rev, path, off+1, lim-1, ents << e, &blk)
128
133
  when Fraggle::Response::Err::RANGE
129
134
  blk.call(ents, nil)
130
135
  else
@@ -136,56 +141,56 @@ module Fraggle
136
141
  # Sends a request to the server. Returns the request with a new tag
137
142
  # assigned.
138
143
  def send(req, &blk)
139
- cb = Proc.new do |e|
140
- log.debug("response: #{e.inspect} for #{req.inspect}")
141
-
142
- if e.disconnected? && cn.err?
143
- log.error("conn err: #{req.inspect}")
144
- reconnect!
144
+ cb = Proc.new do |e, err|
145
+ case err
146
+ when Connection::DisconnectedError
147
+ if cn.err?
148
+ reconnect!
149
+ end
145
150
  end
146
-
147
- blk.call(e)
151
+ blk.call(e, err)
148
152
  end
149
153
 
150
- log.debug("sending: #{req.inspect}")
151
154
  cn.send_request(req, cb)
152
155
  end
153
156
 
154
157
  def resend(req, &blk)
155
- cb = Proc.new do |e|
156
- if e.disconnected?
158
+ send(req) do |e, err|
159
+ case err
160
+ when nil
161
+ blk.call(e, err)
162
+ when Connection::DisconnectedError
157
163
  req.tag = nil
158
- log.debug("resending: #{req.inspect}")
159
164
  resend(req, &blk)
160
165
  else
161
- blk.call(e)
166
+ blk.call(e, err)
162
167
  end
163
168
  end
164
-
165
- send(req, &cb)
166
169
  end
167
170
 
168
171
  def idemp(req, &blk)
169
- cb = Proc.new do |e|
170
- if e.disconnected? && req.rev > 0
172
+ send(req) do |e, err|
173
+ case err
174
+ when Connection::DisconnectedError
171
175
  # If we're trying to update a value that isn't missing or that we're
172
176
  # not trying to clobber, it's safe to retry. We can't idempotently
173
177
  # update missing values because there may be a race with another
174
178
  # client that sets and/or deletes the key during the time between your
175
179
  # read and write.
176
- req.tag = nil
177
- idemp(req, &blk)
178
- next
180
+ if (req.rev || 0) > 0
181
+ req.tag = nil
182
+ idemp(req, &blk)
183
+ else
184
+ blk.call(e, err)
185
+ end
186
+ when nil
187
+ blk.call(e, err)
179
188
  end
180
-
181
- blk.call(e)
182
189
  end
183
-
184
- send(req, &cb)
185
190
  end
186
191
 
187
192
  def reconnect!
188
- if addr = @addrs.shift
193
+ if addr = @addrs.slice!(rand(@addrs.length))
189
194
  reconnect(addr)
190
195
  else
191
196
  raise NoMoreAddrs
@@ -193,7 +198,6 @@ module Fraggle
193
198
  end
194
199
 
195
200
  def reconnect(addr)
196
- log.warn("reconnecting to #{addr}")
197
201
  host, port = addr.split(":")
198
202
  @cn = EM.connect(host, port, Fraggle::Connection, addr)
199
203
  end
@@ -4,21 +4,35 @@ module Fraggle
4
4
 
5
5
  module Connection
6
6
 
7
- Disconnected = Response.new
8
- Disconnected.disconnected = true
9
-
10
- # Base class for all Connection errors
11
- class Error < StandardError
12
- attr_accessor :req
13
-
7
+ # Raised when a request is invalid
8
+ class SendError < StandardError
14
9
  def initialize(req, msg=nil)
15
10
  @req = req
16
11
  super(msg)
17
12
  end
18
13
  end
19
14
 
20
- # Raised when a request is invalid
21
- class SendError < Error
15
+ class DisconnectedError < StandardError
16
+ def ==(o)
17
+ return false if ! o.kind_of?(self.class)
18
+ message == o.message
19
+ end
20
+ end
21
+
22
+ class ResponseError < StandardError
23
+ attr_reader :code
24
+
25
+ alias :detail :message
26
+
27
+ def initialize(res)
28
+ @code = res.err_code
29
+ super("#{res.name_for(Response::Err, code)}: #{res.err_detail}")
30
+ end
31
+
32
+ def ==(o)
33
+ return false if ! o.kind_of?(self.class)
34
+ code == o.code && message == o.message
35
+ end
22
36
  end
23
37
 
24
38
 
@@ -33,10 +47,10 @@ module Fraggle
33
47
 
34
48
  while @buf.length > 0
35
49
  if @len && @buf.length >= @len
36
- bytes = @buf.slice!(0, @len)
37
- @len = nil
38
- res = Response.decode(bytes)
39
- receive_response(res)
50
+ bytes = @buf.slice!(0, @len)
51
+ @len = nil
52
+ res = Response.decode(bytes)
53
+ receive_response(res)
40
54
  elsif @buf.length >= 4
41
55
  bytes = @buf.slice!(0, 4)
42
56
  @len = bytes.unpack("N")[0]
@@ -51,7 +65,11 @@ module Fraggle
51
65
  return if err?
52
66
  req, blk = @cb.delete(res.tag)
53
67
  return if ! blk
54
- blk.call(res)
68
+ if res.err_code
69
+ blk.call(nil, ResponseError.new(res))
70
+ else
71
+ blk.call(res, nil)
72
+ end
55
73
  end
56
74
 
57
75
  def send_request(req, blk)
@@ -60,7 +78,7 @@ module Fraggle
60
78
  end
61
79
 
62
80
  if err?
63
- next_tick { blk.call(Disconnected) }
81
+ next_tick { blk.call(nil, DisconnectedError.new(self.addr)) }
64
82
  return req
65
83
  end
66
84
 
@@ -85,7 +103,7 @@ module Fraggle
85
103
  def unbind
86
104
  @err = true
87
105
  @cb.values.each do |_, blk|
88
- blk.call(Disconnected)
106
+ blk.call(nil, DisconnectedError.new(self.addr))
89
107
  end
90
108
  end
91
109
 
@@ -16,6 +16,7 @@ module Fraggle
16
16
  WALK = 9
17
17
  GETDIR = 14
18
18
  STAT = 16
19
+ ACCESS = 99
19
20
  end
20
21
 
21
22
  optional :tag, :int32, 1
@@ -6,8 +6,6 @@ module Fraggle
6
6
  SET = 4
7
7
  DEL = 8
8
8
 
9
- attr_accessor :disconnected
10
-
11
9
  def set?
12
10
  return false if !flags
13
11
  (flags & SET) > 0
@@ -26,9 +24,5 @@ module Fraggle
26
24
  err_code.nil?
27
25
  end
28
26
 
29
- def disconnected?
30
- !!@disconnected
31
- end
32
-
33
27
  end
34
28
  end
@@ -1,3 +1,3 @@
1
1
  module Fraggle
2
- VERSION = "4.0.0.pre.1"
2
+ VERSION = "4.0.0.pre.2"
3
3
  end
@@ -23,7 +23,7 @@ class FraggleClientTest < Test::Unit::TestCase
23
23
  @c.__send__(:initialize, cn, @addrs)
24
24
  end
25
25
 
26
- def test_send_error
26
+ def test_response_error
27
27
  req, log = request(V::REV)
28
28
 
29
29
  c.send(req, &log)
@@ -31,7 +31,7 @@ class FraggleClientTest < Test::Unit::TestCase
31
31
  res = reply(req.tag, :err_code => E::OTHER)
32
32
  c.cn.receive_response(res)
33
33
 
34
- assert_equal [res], log.valid
34
+ assert_equal [[nil, C::ResponseError.new(res)]], log.valid
35
35
  end
36
36
 
37
37
  def test_reconnect_without_pending_requests
@@ -50,7 +50,7 @@ class FraggleClientTest < Test::Unit::TestCase
50
50
  assert exp.include?(c.cn.addr), "#{c.cn.addr.inspect} not in #{exp.inspect}"
51
51
 
52
52
  # If the client can handle an error, it should not mention it to the user.
53
- assert_equal [Fraggle::Connection::Disconnected], log.valid
53
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], log.valid
54
54
  end
55
55
 
56
56
  def test_reconnect_with_pending_request
@@ -68,7 +68,7 @@ class FraggleClientTest < Test::Unit::TestCase
68
68
 
69
69
  assert exp.include?(c.cn.addr), "#{c.cn.addr.inspect} not in #{exp.inspect}"
70
70
 
71
- assert_equal [Fraggle::Connection::Disconnected], log.valid
71
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], log.valid
72
72
  end
73
73
 
74
74
  def test_reconnect_with_multiple_pending_requests
@@ -93,8 +93,8 @@ class FraggleClientTest < Test::Unit::TestCase
93
93
  assert_equal exp.length - 1, c.addrs.length
94
94
 
95
95
  # If the client can handle an error, it should not mention it to the user.
96
- assert_equal [Fraggle::Connection::Disconnected], loga.valid
97
- assert_equal [Fraggle::Connection::Disconnected], logb.valid
96
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], loga.valid
97
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], logb.valid
98
98
  end
99
99
 
100
100
  def test_resend_pending_requests
@@ -120,8 +120,8 @@ class FraggleClientTest < Test::Unit::TestCase
120
120
 
121
121
  assert_equal [one], c.cn.sent
122
122
 
123
- assert_equal [Fraggle::Connection::Disconnected], zlog.valid
124
- assert_equal [Fraggle::Connection::Disconnected], nlog.valid
123
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], zlog.valid
124
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], nlog.valid
125
125
  end
126
126
 
127
127
  ###
@@ -181,7 +181,7 @@ class FraggleClientTest < Test::Unit::TestCase
181
181
  :offset => 0
182
182
  }
183
183
 
184
- assert_verb exp, :getdir, 0, "/foo", 0
184
+ assert_verb exp, :_getdir, 0, "/foo", 0
185
185
  end
186
186
 
187
187
  def test_rev
@@ -210,7 +210,7 @@ class FraggleClientTest < Test::Unit::TestCase
210
210
  :offset => 0
211
211
  }
212
212
 
213
- assert_verb exp, :walk, 0, "/foo/*", 0
213
+ assert_verb exp, :_walk, 0, "/foo/*", 0
214
214
  end
215
215
 
216
216
  def test_wait
@@ -223,4 +223,13 @@ class FraggleClientTest < Test::Unit::TestCase
223
223
  assert_verb exp, :wait, 0, "/foo/*"
224
224
  end
225
225
 
226
+ def test_wait
227
+ exp = {
228
+ :verb => V::ACCESS,
229
+ :value => "abc"
230
+ }
231
+
232
+ assert_verb exp, :access, "abc"
233
+ end
234
+
226
235
  end
@@ -5,20 +5,16 @@ class FraggleTransactionTest < Test::Unit::TestCase
5
5
 
6
6
  attr_reader :cn
7
7
 
8
- def nop(attrs={})
9
- request(V::NOP, attrs)
10
- end
11
-
12
8
  def setup
13
9
  @cn = TestConn.new("127.0.0.1:0")
14
10
  end
15
11
 
16
12
  def test_tagging
17
- req, _ = nop
13
+ req, _ = request(V::REV)
18
14
  assert_equal 0, cn.send_request(req, _).tag
19
- req, _ = nop
15
+ req, _ = request(V::REV)
20
16
  assert_equal 1, cn.send_request(req, _).tag
21
- req, _ = nop
17
+ req, _ = request(V::REV)
22
18
  assert_equal 2, cn.send_request(req, _).tag
23
19
  end
24
20
 
@@ -30,7 +26,7 @@ class FraggleTransactionTest < Test::Unit::TestCase
30
26
  res = reply(req.tag)
31
27
  cn.receive_response(res)
32
28
 
33
- assert_equal [res], log.valid
29
+ assert_equal [[res, nil]], log.valid
34
30
  end
35
31
 
36
32
  def test_error
@@ -41,7 +37,8 @@ class FraggleTransactionTest < Test::Unit::TestCase
41
37
  res = reply(req.tag, :err_code => E::OTHER)
42
38
  cn.receive_response(res)
43
39
 
44
- assert_equal [res], log.valid
40
+ err = C::ResponseError.new(res)
41
+ assert_equal [[nil, err]], log.valid
45
42
  end
46
43
 
47
44
  def test_invalid_tag
@@ -63,7 +60,7 @@ class FraggleTransactionTest < Test::Unit::TestCase
63
60
  # This should be ignored
64
61
  cn.receive_response(res)
65
62
 
66
- assert_equal [res], log.valid
63
+ assert_equal [[res, nil]], log.valid
67
64
  end
68
65
 
69
66
  def test_error_deletes_callback
@@ -77,14 +74,14 @@ class FraggleTransactionTest < Test::Unit::TestCase
77
74
  # This should be ignored
78
75
  cn.receive_response(res)
79
76
 
80
- assert_equal [res], log.valid
77
+ assert_equal [[nil, C::ResponseError.new(res)]], log.valid
81
78
  end
82
79
 
83
80
  def test_cannot_reuse_sent_request
84
81
  req, _ = request(V::REV)
85
82
  cn.send_request(req, _)
86
83
 
87
- assert_raises Fraggle::Connection::SendError do
84
+ assert_raises C::SendError do
88
85
  cn.send_request(req, _)
89
86
  end
90
87
  end
@@ -99,9 +96,9 @@ class FraggleTransactionTest < Test::Unit::TestCase
99
96
 
100
97
  cn.unbind
101
98
 
102
- assert_equal [Fraggle::Connection::Disconnected], al.valid
103
- assert_equal [Fraggle::Connection::Disconnected], bl.valid
104
- assert_equal [Fraggle::Connection::Disconnected], cl.valid
99
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], al.valid
100
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], bl.valid
101
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], cl.valid
105
102
  end
106
103
 
107
104
  def test_send_when_disconnected
@@ -114,6 +111,6 @@ class FraggleTransactionTest < Test::Unit::TestCase
114
111
 
115
112
  cn.tick!
116
113
 
117
- assert_equal [Fraggle::Connection::Disconnected], log.valid
114
+ assert_equal [[nil, C::DisconnectedError.new("127.0.0.1:0")]], log.valid
118
115
  end
119
116
  end
@@ -46,6 +46,7 @@ end
46
46
 
47
47
  class Test::Unit::TestCase
48
48
 
49
+ C = Fraggle::Connection
49
50
  V = Fraggle::Request::Verb
50
51
  F = Fraggle::Response
51
52
  E = Fraggle::Response::Err
@@ -57,13 +58,13 @@ class Test::Unit::TestCase
57
58
  @valid = []
58
59
  end
59
60
 
60
- def call(e)
61
- @valid << e
61
+ def call(e, err)
62
+ @valid << [e, err]
62
63
  end
63
64
 
64
65
  def to_proc
65
66
  me = self
66
- Proc.new {|e| me.call(e) }
67
+ Proc.new {|e, err| me.call(e, err) }
67
68
  end
68
69
  end
69
70
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fraggle
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1923831851
4
+ hash: 1923831853
5
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
+ - 2
12
+ version: 4.0.0.pre.2
13
13
  platform: ruby
14
14
  authors:
15
15
  - Blake Mizerany
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2011-05-02 00:00:00 -07:00
20
+ date: 2011-05-05 00:00:00 -07:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
@@ -63,6 +63,20 @@ dependencies:
63
63
  version: "0"
64
64
  type: :development
65
65
  version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: statsample
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ type: :development
79
+ version_requirements: *id004
66
80
  description: An EventMachine Client for Doozer
67
81
  email:
68
82
  - blake.mizerany@gmail.com
@@ -78,10 +92,10 @@ files:
78
92
  - LICENSE
79
93
  - README.md
80
94
  - Rakefile
81
- - bench/gets.rb
82
- - example/getdir_all.rb
95
+ - bench/gs.rb
96
+ - example/getdir.rb
83
97
  - example/readme.rb
84
- - example/walk_all.rb
98
+ - example/walk.rb
85
99
  - example/watch.rb
86
100
  - fraggle.gemspec
87
101
  - lib/fraggle.rb
@@ -1,32 +0,0 @@
1
- require 'rubygems'
2
- require 'eventmachine'
3
- require 'fraggle'
4
-
5
- reqs = 0
6
-
7
- def rget(c, path, rev, &blk)
8
- c.get(path, rev) do |e|
9
- blk.call
10
- rget(c, path, rev, &blk)
11
- end
12
- end
13
-
14
- EM.run do
15
- c = Fraggle.connect
16
-
17
- EM.add_timer(1) do
18
- # The primer is done. Reset `reqs` and do it for real.
19
- reqs = 0
20
- EM.add_timer(1) do
21
- EM.stop_event_loop
22
- end
23
- end
24
-
25
- c.rev do |v|
26
- rget(c, "/ctl/cal/0", v.rev) do
27
- reqs += 1
28
- end
29
- end
30
- end
31
-
32
- puts "Result (GET): #{reqs}/sec"