Class: Fraggle::Client

Inherits:
Object
  • Object
show all
Includes:
Request::Verb
Defined in:
lib/fraggle/client.rb

Constant Summary collapse

MaxInt64 =
1<<63 - 1

Constants included from Request::Verb

Request::Verb::ACCESS, Request::Verb::DEL, Request::Verb::GET, Request::Verb::GETDIR, Request::Verb::NOP, Request::Verb::REV, Request::Verb::SET, Request::Verb::STAT, Request::Verb::WAIT, Request::Verb::WALK

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cn, addrs) ⇒ Client

Returns a new instance of Client.



12
13
14
15
# File 'lib/fraggle/client.rb', line 12

def initialize(cn, addrs)
  @cn, @addrs = cn, addrs
  @attempt = Proc.new {|_| true }
end

Instance Attribute Details

#addrsObject (readonly)

Returns the value of attribute addrs.



10
11
12
# File 'lib/fraggle/client.rb', line 10

def addrs
  @addrs
end

#cnObject (readonly)

Returns the value of attribute cn.



10
11
12
# File 'lib/fraggle/client.rb', line 10

def cn
  @cn
end

Instance Method Details

#_getdir(rev, path, offset, &blk) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/fraggle/client.rb', line 49

def _getdir(rev, path, offset, &blk)
  req = Request.new
  req.verb   = GETDIR
  req.rev    = rev
  req.path   = path
  req.offset = offset

  resend(req, &blk)
end

#_walk(rev, path, offset, &blk) ⇒ Object



59
60
61
62
63
64
65
66
67
# File 'lib/fraggle/client.rb', line 59

def _walk(rev, path, offset, &blk)
  req = Request.new
  req.verb   = WALK
  req.rev    = rev
  req.path   = path
  req.offset = offset

  resend(req, &blk)
end

#access(secret, &blk) ⇒ Object



96
97
98
99
100
101
102
# File 'lib/fraggle/client.rb', line 96

def access(secret, &blk)
  req = Request.new
  req.verb  = ACCESS
  req.value = secret

  resend(req, &blk)
end

#addrObject



17
18
19
# File 'lib/fraggle/client.rb', line 17

def addr
  cn.addr
end

#all(m, rev, path, off, lim, ents = [], &blk) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/fraggle/client.rb', line 121

def all(m, rev, path, off, lim, ents=[], &blk)
  # We're decrementing lim as we go, so we need to return
  # the accumulated values
  if lim == 0
    cn.next_tick { blk.call(ents, nil) }
    return
  end

  __send__(m, rev, path, off) do |e, err|
    case err && err.code
    when nil
      all(m, rev, path, off+1, lim-1, ents << e, &blk)
    when Fraggle::Response::Err::RANGE
      blk.call(ents, nil)
    else
      blk.call(nil, e)
    end
  end
end

#attempt(&blk) ⇒ Object

Setting ‘blk` will cause a client to call it before attempting to reconnect. `blk` is called with one parameter `addr`, which is the address that will be for reconnect.



194
195
196
# File 'lib/fraggle/client.rb', line 194

def attempt(&blk)
  @attempt = blk
end

#del(rev, path, &blk) ⇒ Object



40
41
42
43
44
45
46
47
# File 'lib/fraggle/client.rb', line 40

def del(rev, path, &blk)
  req = Request.new
  req.verb = DEL
  req.rev  = rev
  req.path = path

  idemp(req, &blk)
end

#get(rev, path, &blk) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/fraggle/client.rb', line 31

def get(rev, path, &blk)
  req = Request.new
  req.verb = GET
  req.rev  = rev
  req.path = path

  resend(req, &blk)
end

#getdir(rev, path, off = 0, lim = MaxInt64, ents = [], &blk) ⇒ Object



113
114
115
# File 'lib/fraggle/client.rb', line 113

def getdir(rev, path, off=0, lim=MaxInt64, ents=[], &blk)
  all(:_getdir, rev, path, off, lim, ents, &blk)
end

#idemp(req, &blk) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/fraggle/client.rb', line 169

def idemp(req, &blk)
  send(req) do |e, err|
    case err
    when Connection::DisconnectedError
      # If we're trying to update a value that isn't missing or that we're
      # not trying to clobber, it's safe to retry.  We can't idempotently
      # update missing values because there may be a race with another
      # client that sets and/or deletes the key during the time between your
      # read and write.
      if (req.rev || 0) > 0
        req.tag = nil
        idemp(req, &blk)
      else
        blk.call(e, err)
      end
    else
      blk.call(e, err)
    end
  end
end

#reconnect(addr) ⇒ Object



205
206
207
208
# File 'lib/fraggle/client.rb', line 205

def reconnect(addr)
  host, port = addr.split(":")
  @cn = EM.connect(host, port, Fraggle::Connection, addr)
end

#reconnect!Object



198
199
200
201
202
203
# File 'lib/fraggle/client.rb', line 198

def reconnect!
  addr = @addrs.slice(rand(@addrs.length))
  if @attempt.call(addr)
    reconnect(addr)
  end
end

#resend(req, &blk) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
# File 'lib/fraggle/client.rb', line 157

def resend(req, &blk)
  send(req) do |e, err|
    case err
    when Connection::DisconnectedError
      req.tag = nil
      resend(req, &blk)
    else
      blk.call(e, err)
    end
  end
end

#rev(&blk) ⇒ Object



78
79
80
81
82
83
84
85
# File 'lib/fraggle/client.rb', line 78

def rev(&blk)
  req = Request.new
  req.verb = REV

  resend(req) do |v, _|
    blk.call(v.rev)
  end
end

#send(req, &blk) ⇒ Object

Sends a request to the server. Returns the request with a new tag assigned.



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/fraggle/client.rb', line 143

def send(req, &blk)
  cb = Proc.new do |e, err|
    case err
    when Connection::DisconnectedError
      if cn.err?
        reconnect!
      end
    end
    blk.call(e, err)
  end

  cn.send_request(req, cb)
end

#set(rev, path, value, &blk) ⇒ Object



21
22
23
24
25
26
27
28
29
# File 'lib/fraggle/client.rb', line 21

def set(rev, path, value, &blk)
  req = Request.new
  req.verb  = SET
  req.rev   = rev
  req.path  = path
  req.value = value

  idemp(req, &blk)
end

#stat(rev, path, &blk) ⇒ Object



87
88
89
90
91
92
93
94
# File 'lib/fraggle/client.rb', line 87

def stat(rev, path, &blk)
  req = Request.new
  req.rev  = rev
  req.verb = STAT
  req.path = path

  resend(req, &blk)
end

#wait(rev, path, &blk) ⇒ Object



69
70
71
72
73
74
75
76
# File 'lib/fraggle/client.rb', line 69

def wait(rev, path, &blk)
  req = Request.new
  req.verb = WAIT
  req.rev  = rev
  req.path = path

  resend(req, &blk)
end

#walk(rev, path, off = 0, lim = MaxInt64, ents = [], &blk) ⇒ Object



117
118
119
# File 'lib/fraggle/client.rb', line 117

def walk(rev, path, off=0, lim=MaxInt64, ents=[], &blk)
  all(:_walk, rev, path, off, lim, ents, &blk)
end

#watch(rev, path, &blk) ⇒ Object



104
105
106
107
108
109
110
111
# File 'lib/fraggle/client.rb', line 104

def watch(rev, path, &blk)
  wait(rev, path) do |e, err|
    blk.call(e, err)
    if ! err
      watch(e.rev+1, path, &blk)
    end
  end
end