beanstalk-client 0.9.0 → 0.10.0
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/History.txt +7 -0
- data/Manifest.txt +0 -1
- data/lib/beanstalk-client/connection.rb +100 -97
- data/lib/beanstalk-client/errors.rb +20 -4
- data/lib/beanstalk-client/version.rb +1 -1
- data/website/index.html +1 -1
- metadata +2 -3
- data/lib/beanstalk-client/bag.rb +0 -36
data/History.txt
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
== 0.10.0 2008-04-11
|
2
|
+
|
3
|
+
* Some optimizations to avoid sending unnecessary use and watch commands.
|
4
|
+
* Use newer protocol features to open only one connection per server address.
|
5
|
+
* More consistent and complete peek methods.
|
6
|
+
* Various bug fixes.
|
7
|
+
|
1
8
|
== 0.9.0 2008-02-27
|
2
9
|
|
3
10
|
* Skipping 0.8.x; beanstalkd 0.8 was a botched release.
|
data/Manifest.txt
CHANGED
@@ -19,18 +19,19 @@ require 'socket'
|
|
19
19
|
require 'fcntl'
|
20
20
|
require 'yaml'
|
21
21
|
require 'set'
|
22
|
-
require 'beanstalk-client/bag'
|
23
22
|
require 'beanstalk-client/errors'
|
24
23
|
require 'beanstalk-client/job'
|
25
24
|
|
26
25
|
module Beanstalk
|
27
|
-
class
|
26
|
+
class Connection
|
28
27
|
attr_reader :addr
|
29
28
|
|
30
29
|
def initialize(addr, jptr=self)
|
31
30
|
@addr = addr
|
32
31
|
@jptr = jptr
|
33
32
|
connect
|
33
|
+
@last_used = 'default'
|
34
|
+
@watch_list = ['default']
|
34
35
|
end
|
35
36
|
|
36
37
|
def connect
|
@@ -47,98 +48,116 @@ module Beanstalk
|
|
47
48
|
end
|
48
49
|
|
49
50
|
def put(body, pri=65536, delay=0, ttr=120)
|
50
|
-
|
51
|
-
|
51
|
+
interact("put #{pri} #{delay} #{ttr} #{body.size}\r\n#{body}\r\n",
|
52
|
+
%w(INSERTED BURIED))[0].to_i
|
52
53
|
end
|
53
54
|
|
54
55
|
def yput(obj, pri=65536, delay=0, ttr=120)
|
55
56
|
put(YAML.dump(obj), pri, delay, ttr)
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
-
|
60
|
-
begin
|
61
|
-
Job.new(@jptr, *read_job('FOUND'))
|
62
|
-
rescue UnexpectedResponse
|
63
|
-
nil
|
64
|
-
end
|
59
|
+
def peek_job(id)
|
60
|
+
interact("peek #{id}\r\n", :job)
|
65
61
|
end
|
66
62
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
63
|
+
def peek_ready()
|
64
|
+
interact("peek-ready\r\n", :job)
|
65
|
+
end
|
66
|
+
|
67
|
+
def peek_delayed()
|
68
|
+
interact("peek-delayed\r\n", :job)
|
69
|
+
end
|
70
|
+
|
71
|
+
def peek_buried()
|
72
|
+
interact("peek-buried\r\n", :job)
|
70
73
|
end
|
71
74
|
|
72
75
|
def reserve()
|
76
|
+
raise WaitingForJobError if @waiting
|
73
77
|
@socket.write("reserve\r\n")
|
78
|
+
|
79
|
+
begin
|
80
|
+
@waiting = true
|
81
|
+
# Give the user a chance to select on multiple fds.
|
82
|
+
Beanstalk.select.call([@socket]) if Beanstalk.select
|
83
|
+
rescue WaitingForJobError
|
84
|
+
# just continue
|
85
|
+
ensure
|
86
|
+
@waiting = false
|
87
|
+
end
|
88
|
+
|
74
89
|
Job.new(@jptr, *read_job('RESERVED'))
|
75
90
|
end
|
76
91
|
|
77
92
|
def delete(id)
|
78
|
-
|
79
|
-
check_resp('DELETED')
|
93
|
+
interact("delete #{id}\r\n", %w(DELETED))
|
80
94
|
:ok
|
81
95
|
end
|
82
96
|
|
83
97
|
def release(id, pri, delay)
|
84
|
-
|
85
|
-
check_resp('RELEASED')
|
98
|
+
interact("release #{id} #{pri} #{delay}\r\n", %w(RELEASED))
|
86
99
|
:ok
|
87
100
|
end
|
88
101
|
|
89
102
|
def bury(id, pri)
|
90
|
-
|
91
|
-
check_resp('BURIED')
|
103
|
+
interact("bury #{id} #{pri}\r\n", %w(BURIED))
|
92
104
|
:ok
|
93
105
|
end
|
94
106
|
|
95
107
|
def use(tube)
|
96
|
-
|
97
|
-
|
108
|
+
return tube if tube == @last_used
|
109
|
+
@last_used = interact("use #{tube}\r\n", %w(USING))[0]
|
98
110
|
end
|
99
111
|
|
100
112
|
def watch(tube)
|
101
|
-
@
|
102
|
-
|
113
|
+
return @watch_list.size if @watch_list.include?(tube)
|
114
|
+
r = interact("watch #{tube}\r\n", %w(WATCHING))[0].to_i
|
115
|
+
@watch_list += [tube]
|
116
|
+
return r
|
103
117
|
end
|
104
118
|
|
105
119
|
def ignore(tube)
|
106
|
-
@
|
107
|
-
|
120
|
+
return @watch_list.size if !@watch_list.include?(tube)
|
121
|
+
r = interact("ignore #{tube}\r\n", %w(WATCHING))[0].to_i
|
122
|
+
@watch_list -= [tube]
|
123
|
+
return r
|
108
124
|
end
|
109
125
|
|
110
126
|
def stats()
|
111
|
-
|
112
|
-
read_yaml('OK')
|
127
|
+
interact("stats\r\n", :yaml)
|
113
128
|
end
|
114
129
|
|
115
130
|
def job_stats(id)
|
116
|
-
|
117
|
-
read_yaml('OK')
|
131
|
+
interact("stats-job #{id}\r\n", :yaml)
|
118
132
|
end
|
119
133
|
|
120
134
|
def stats_tube(tube)
|
121
|
-
|
122
|
-
read_yaml('OK')
|
135
|
+
interact("stats-tube #{tube}\r\n", :yaml)
|
123
136
|
end
|
124
137
|
|
125
138
|
def list_tubes()
|
126
|
-
|
127
|
-
read_yaml('OK')
|
139
|
+
interact("list-tubes\r\n", :yaml)
|
128
140
|
end
|
129
141
|
|
130
142
|
def list_tube_used()
|
131
|
-
|
132
|
-
check_resp('USING')[0]
|
143
|
+
interact("list-tube-used\r\n", %w(USING))[0]
|
133
144
|
end
|
134
145
|
|
135
|
-
def list_tubes_watched()
|
136
|
-
@
|
137
|
-
|
146
|
+
def list_tubes_watched(cached=false)
|
147
|
+
return @watch_list if cached
|
148
|
+
@watch_list = interact("list-tubes-watched\r\n", :yaml)
|
138
149
|
end
|
139
150
|
|
140
151
|
private
|
141
152
|
|
153
|
+
def interact(cmd, rfmt)
|
154
|
+
raise WaitingForJobError if @waiting
|
155
|
+
@socket.write(cmd)
|
156
|
+
return read_yaml('OK') if rfmt == :yaml
|
157
|
+
return found_job if rfmt == :job
|
158
|
+
check_resp(*rfmt)
|
159
|
+
end
|
160
|
+
|
142
161
|
def get_resp()
|
143
162
|
r = @socket.gets("\r\n")
|
144
163
|
raise EOFError if r == nil
|
@@ -149,15 +168,18 @@ module Beanstalk
|
|
149
168
|
r = get_resp()
|
150
169
|
rword, *vals = r.split(/\s+/)
|
151
170
|
if (words.size > 0) and !words.include?(rword)
|
152
|
-
raise UnexpectedResponse.
|
171
|
+
raise UnexpectedResponse.classify(rword, r)
|
153
172
|
end
|
154
173
|
vals
|
155
174
|
end
|
156
175
|
|
157
|
-
def
|
158
|
-
|
159
|
-
|
176
|
+
def found_job()
|
177
|
+
Job.new(@jptr, *read_job('FOUND'))
|
178
|
+
rescue NotFoundError
|
179
|
+
nil
|
180
|
+
end
|
160
181
|
|
182
|
+
def read_job(word)
|
161
183
|
id, bytes = check_resp(word).map{|s| s.to_i}
|
162
184
|
body = read_bytes(bytes)
|
163
185
|
raise 'bad trailer' if read_bytes(2) != "\r\n"
|
@@ -179,47 +201,6 @@ module Beanstalk
|
|
179
201
|
end
|
180
202
|
end
|
181
203
|
|
182
|
-
# Same interface as RawConnection.
|
183
|
-
# With this you can reserve more than one job at a time.
|
184
|
-
class Connection
|
185
|
-
attr_reader :addr
|
186
|
-
|
187
|
-
def initialize(addr, jptr=self)
|
188
|
-
@addr = addr
|
189
|
-
@misc = RawConnection.new(addr, jptr)
|
190
|
-
@free = Bag.new{RawConnection.new(addr, jptr)}
|
191
|
-
@used = {}
|
192
|
-
end
|
193
|
-
|
194
|
-
def reserve()
|
195
|
-
c = @free.take()
|
196
|
-
j = c.reserve()
|
197
|
-
@used[j.id] = c
|
198
|
-
j
|
199
|
-
ensure
|
200
|
-
@free.give(c) if c and not j
|
201
|
-
end
|
202
|
-
|
203
|
-
def delete(id)
|
204
|
-
@used[id].delete(id)
|
205
|
-
@free.give(@used.delete(id))
|
206
|
-
end
|
207
|
-
|
208
|
-
def release(id, pri, delay)
|
209
|
-
@used[id].release(id, pri, delay)
|
210
|
-
@free.give(@used.delete(id))
|
211
|
-
end
|
212
|
-
|
213
|
-
def bury(id, pri)
|
214
|
-
@used[id].bury(id, pri)
|
215
|
-
@free.give(@used.delete(id))
|
216
|
-
end
|
217
|
-
|
218
|
-
def method_missing(selector, *args, &block)
|
219
|
-
@misc.send(selector, *args, &block)
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
204
|
class CleanupWrapper
|
224
205
|
def initialize(addr, multi)
|
225
206
|
@conn = Connection.new(addr, self)
|
@@ -266,14 +247,6 @@ module Beanstalk
|
|
266
247
|
@last_conn.addr
|
267
248
|
end
|
268
249
|
|
269
|
-
def send_to_rand_conn(sel, *args)
|
270
|
-
wrap(pick_connection, sel, *args)
|
271
|
-
end
|
272
|
-
|
273
|
-
def send_to_all_conns(sel, *args)
|
274
|
-
make_hash(@connections.map{|a, c| [a, wrap(c, sel, *args)]})
|
275
|
-
end
|
276
|
-
|
277
250
|
def put(body, pri=65536, delay=0, ttr=120)
|
278
251
|
send_to_rand_conn(:put, body, pri, delay, ttr)
|
279
252
|
end
|
@@ -332,20 +305,46 @@ module Beanstalk
|
|
332
305
|
|
333
306
|
def close
|
334
307
|
while @connections.size > 0
|
335
|
-
addr
|
308
|
+
addr = @connections.keys.last
|
309
|
+
conn = @connections[addr]
|
310
|
+
@connections.delete(addr)
|
336
311
|
conn.close
|
337
312
|
end
|
338
313
|
end
|
339
314
|
|
340
|
-
def
|
315
|
+
def peek_ready()
|
316
|
+
send_to_each_conn_first_res(:peek_ready)
|
317
|
+
end
|
318
|
+
|
319
|
+
def peek_delayed()
|
320
|
+
send_to_each_conn_first_res(:peek_delayed)
|
321
|
+
end
|
322
|
+
|
323
|
+
def peek_buried()
|
324
|
+
send_to_each_conn_first_res(:peek_buried)
|
325
|
+
end
|
326
|
+
|
327
|
+
def peek_job(id)
|
328
|
+
make_hash(send_to_all_conns(:peek_job, id))
|
329
|
+
end
|
330
|
+
|
331
|
+
private
|
332
|
+
|
333
|
+
def send_to_each_conn_first_res(sel, *args)
|
341
334
|
open_connections.each do |c|
|
342
|
-
|
343
|
-
return
|
335
|
+
x = wrap(c, sel, *args)
|
336
|
+
return x if x
|
344
337
|
end
|
345
338
|
nil
|
346
339
|
end
|
347
340
|
|
348
|
-
|
341
|
+
def send_to_rand_conn(sel, *args)
|
342
|
+
wrap(pick_connection, sel, *args)
|
343
|
+
end
|
344
|
+
|
345
|
+
def send_to_all_conns(sel, *args)
|
346
|
+
compact_hash(make_hash(@connections.map{|a, c| [a, wrap(c, sel, *args)]}))
|
347
|
+
end
|
349
348
|
|
350
349
|
def pick_connection()
|
351
350
|
open_connections[rand(open_connections.size)] or raise NotConnected
|
@@ -365,6 +364,10 @@ module Beanstalk
|
|
365
364
|
Hash[*pairs.inject([]){|a,b|a+b}]
|
366
365
|
end
|
367
366
|
|
367
|
+
def compact_hash(hash)
|
368
|
+
hash.reject{|k,v| v == nil}
|
369
|
+
end
|
370
|
+
|
368
371
|
def sum_hashes(hs)
|
369
372
|
hs.inject({}){|a,b| a.merge(b) {|k,o,n| combine_stats(k, o, n)}}
|
370
373
|
end
|
@@ -20,14 +20,30 @@ module Beanstalk
|
|
20
20
|
end
|
21
21
|
|
22
22
|
class UnexpectedResponse < RuntimeError
|
23
|
-
def self.
|
24
|
-
|
25
|
-
|
23
|
+
def self.subclasses
|
24
|
+
@classes ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.inherited(subclass)
|
28
|
+
subclasses << subclass
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.classify(word, message)
|
32
|
+
for clas in subclasses
|
33
|
+
return clas.new(message) if clas::WORD == word
|
26
34
|
end
|
27
|
-
|
35
|
+
return new(message)
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
31
39
|
class DrainingError < UnexpectedResponse
|
40
|
+
WORD = 'DRAINING'
|
41
|
+
end
|
42
|
+
|
43
|
+
class NotFoundError < UnexpectedResponse
|
44
|
+
WORD = 'NOT_FOUND'
|
45
|
+
end
|
46
|
+
|
47
|
+
class WaitingForJobError < RuntimeError
|
32
48
|
end
|
33
49
|
end
|
data/website/index.html
CHANGED
@@ -33,7 +33,7 @@
|
|
33
33
|
<h1>Beanstalk Client</h1>
|
34
34
|
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/beanstalk"; return false'>
|
35
35
|
<p>Get Version</p>
|
36
|
-
<a href="http://rubyforge.org/projects/beanstalk" class="numbers">0.
|
36
|
+
<a href="http://rubyforge.org/projects/beanstalk" class="numbers">0.10.0</a>
|
37
37
|
</div>
|
38
38
|
<h1>→ ‘beanstalk-client’</h1>
|
39
39
|
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: beanstalk-client
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2008-
|
6
|
+
version: 0.10.0
|
7
|
+
date: 2008-04-11 00:00:00 -07:00
|
8
8
|
summary: Ruby client library for the Beanstalk protocol
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -37,7 +37,6 @@ files:
|
|
37
37
|
- config/hoe.rb
|
38
38
|
- config/requirements.rb
|
39
39
|
- lib/beanstalk-client.rb
|
40
|
-
- lib/beanstalk-client/bag.rb
|
41
40
|
- lib/beanstalk-client/connection.rb
|
42
41
|
- lib/beanstalk-client/errors.rb
|
43
42
|
- lib/beanstalk-client/job.rb
|
data/lib/beanstalk-client/bag.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# beanstalk-client/bag.rb - client library for beanstalk
|
2
|
-
|
3
|
-
# Copyright (C) 2007 Philotic Inc.
|
4
|
-
|
5
|
-
# This program is free software: you can redistribute it and/or modify
|
6
|
-
# it under the terms of the GNU General Public License as published by
|
7
|
-
# the Free Software Foundation, either version 3 of the License, or
|
8
|
-
# (at your option) any later version.
|
9
|
-
|
10
|
-
# This program is distributed in the hope that it will be useful,
|
11
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
-
# GNU General Public License for more details.
|
14
|
-
|
15
|
-
# You should have received a copy of the GNU General Public License
|
16
|
-
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
-
|
18
|
-
class Beanstalk::Bag
|
19
|
-
def initialize(initial_size=0, &default)
|
20
|
-
@default = default
|
21
|
-
@items = []
|
22
|
-
initial_size.times{give(default.call())}
|
23
|
-
end
|
24
|
-
|
25
|
-
def give(x)
|
26
|
-
(@items << x)[-1]
|
27
|
-
end
|
28
|
-
|
29
|
-
def take()
|
30
|
-
@items.pop or @default.call()
|
31
|
-
end
|
32
|
-
|
33
|
-
def size()
|
34
|
-
@items.size
|
35
|
-
end
|
36
|
-
end
|