gemerald_beanstalk 0.0.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/.gitignore +17 -0
- data/.travis.yml +27 -0
- data/Gemfile +8 -0
- data/LICENSE +22 -0
- data/README.md +67 -0
- data/Rakefile +19 -0
- data/gemerald_beanstalk.gemspec +25 -0
- data/lib/gemerald_beanstalk.rb +10 -0
- data/lib/gemerald_beanstalk/beanstalk.rb +289 -0
- data/lib/gemerald_beanstalk/beanstalk_helper.rb +300 -0
- data/lib/gemerald_beanstalk/command.rb +365 -0
- data/lib/gemerald_beanstalk/connection.rb +170 -0
- data/lib/gemerald_beanstalk/job.rb +229 -0
- data/lib/gemerald_beanstalk/jobs.rb +39 -0
- data/lib/gemerald_beanstalk/server.rb +54 -0
- data/lib/gemerald_beanstalk/tube.rb +164 -0
- data/lib/gemerald_beanstalk/version.rb +3 -0
- data/test/beanstalk_integration_tests_test.rb +2 -0
- data/test/test_helper.rb +8 -0
- metadata +133 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
language: ruby
|
2
|
+
|
3
|
+
rvm:
|
4
|
+
- 1.9.3
|
5
|
+
- 2.0.0
|
6
|
+
- jruby-19mode
|
7
|
+
- rbx-19mode
|
8
|
+
|
9
|
+
before_script:
|
10
|
+
- bundle config
|
11
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || git clone https://github.com/beanstalkd/beaneater.git /tmp/beaneater'
|
12
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || BUNDLE_GEMFILE=/tmp/beaneater/Gemfile bundle install'
|
13
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || git clone https://github.com/nesquena/backburner.git /tmp/backburner'
|
14
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || BUNDLE_GEMFILE=/tmp/backburner/Gemfile bundle install'
|
15
|
+
|
16
|
+
script:
|
17
|
+
- rake test
|
18
|
+
- sudo sed -i 's/^\(127.0.0.1.*\)$/\1 coveralls.io/' /etc/hosts
|
19
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || rake start_gemerald_beanstalk_test_server &'
|
20
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || cd /tmp/beaneater'
|
21
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || BUNDLE_GEMFILE=/tmp/beaneater/Gemfile bundle exec rake test:full'
|
22
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || cd /tmp/backburner'
|
23
|
+
- '[ "$TRAVIS_RUBY_VERSION" = "jruby-19mode" ] && (exit 0) || BUNDLE_GEMFILE=/tmp/backburner/Gemfile bundle exec rake'
|
24
|
+
|
25
|
+
matrix:
|
26
|
+
allow_failures:
|
27
|
+
- rvm: jruby-19mode
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Freewrite.org
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# GemeraldBeanstalk
|
2
|
+
[](https://travis-ci.org/gemeraldbeanstalk/gemerald_beanstalk)
|
3
|
+
[](https://coveralls.io/r/gemeraldbeanstalk/gemerald_beanstalk)
|
4
|
+
[](https://codeclimate.com/github/gemeraldbeanstalk/gemerald_beanstalk)
|
5
|
+
[](https://gemnasium.com/gemeraldbeanstalk/gemerald_beanstalk)
|
6
|
+
|
7
|
+
|
8
|
+
GemeraldBeanstalk offers a Ruby implementation of beanstalkd for testing and other uses.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
GemeraldBeanstalk should work as a drop in replacement for beanstalkd. You can
|
13
|
+
start a server via GemeraldBeanstalk::Server.start:
|
14
|
+
```ruby
|
15
|
+
|
16
|
+
# Start a GemeraldBeanstalk bound to 0.0.0.0:11300
|
17
|
+
GemeraldBeanstalk::Server.start
|
18
|
+
|
19
|
+
# Customize server binding
|
20
|
+
GemeraldBeanstalk::Server.start('192.168.1.10', 11301)
|
21
|
+
```
|
22
|
+
|
23
|
+
GemeraldBeanstalk::Server.start returns an array containing the Thread the
|
24
|
+
server is running in and the server's GemeraldBeanstalk::Beanstalk instance.
|
25
|
+
|
26
|
+
The internals of GemeraldBeanstalk are undocumented at this point, with the
|
27
|
+
expectation being that it should be interacted with strictly via the [beanstalkd
|
28
|
+
protocol](https://github.com/kr/beanstalkd/blob/master/doc/protocol.md). This
|
29
|
+
will likely change in the future, allowing more programatic access directly to
|
30
|
+
the GemeraldBeanstalk::Beanstalk.
|
31
|
+
|
32
|
+
## Installation
|
33
|
+
|
34
|
+
Add this line to your application's Gemfile:
|
35
|
+
|
36
|
+
gem 'gemerald_beanstalk'
|
37
|
+
|
38
|
+
And then execute:
|
39
|
+
|
40
|
+
$ bundle
|
41
|
+
|
42
|
+
Or install it yourself as:
|
43
|
+
|
44
|
+
$ gem install gemerald_beanstalk
|
45
|
+
|
46
|
+
## Unbugs!
|
47
|
+
In the process of building GemeraldBeanstalk, a number of bugs and inconsistencies
|
48
|
+
with Beanstalkd protocol were discovered. Patches have been submitted to correct
|
49
|
+
the various bugs and inconsistencies, but they have not yet been merged into
|
50
|
+
beanstalkd.
|
51
|
+
|
52
|
+
It would be fairly tedious to reproduce the behavior of some of the bugs, and as
|
53
|
+
such, GemeraldBeanstalk doesn't suffer from them. This can be troubling when
|
54
|
+
you run tests that work against GemeraldBeanstalk, but then fail against an
|
55
|
+
actual beanstalkd server. Below are a list of those protocol issues that exist
|
56
|
+
with Beanstalk, but not with GemeraldBeanstalk.
|
57
|
+
* [Pause tube should check tube name valid](https://github.com/kr/beanstalkd/pull/217)
|
58
|
+
* [Can't ignore tube with name 200 chars long](https://github.com/kr/beanstalkd/issues/212)
|
59
|
+
* [Use of 200-char tube name causes INTERNAL_ERROR](https://github.com/kr/beanstalkd/issues/211)
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
1. Fork it
|
64
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
65
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'gemerald_beanstalk'
|
4
|
+
|
5
|
+
|
6
|
+
Rake::TestTask.new do |t|
|
7
|
+
t.libs << 'test'
|
8
|
+
t.pattern = 'test/**/*_test.rb'
|
9
|
+
end
|
10
|
+
|
11
|
+
task :start_gemerald_beanstalk_test_server do
|
12
|
+
Thread.abort_on_exception = true
|
13
|
+
server_thread, beanstalk = GemeraldBeanstalk::Server.start(ENV['BIND_ADDRESS'], ENV['PORT'])
|
14
|
+
trap("SIGINT") { server_thread.kill }
|
15
|
+
puts "GemeraldBeanstalk listening on #{beanstalk.address}"
|
16
|
+
server_thread.join
|
17
|
+
end
|
18
|
+
|
19
|
+
task :default => :test
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gemerald_beanstalk/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'gemerald_beanstalk'
|
8
|
+
spec.version = GemeraldBeanstalk::VERSION
|
9
|
+
spec.authors = ['Freewrite.org']
|
10
|
+
spec.email = ['dev@freewrite.org']
|
11
|
+
spec.description = %q{RubyGem implementation of beanstalkd}
|
12
|
+
spec.summary = %q{Gemerald Beanstalk offers a Ruby implementation of beanstalkd for testing and other uses.}
|
13
|
+
spec.homepage = 'https://github.com/gemeraldbeanstalk/gemerald_beanstalk'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^test/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'eventmachine'
|
22
|
+
spec.add_dependency 'thread_safe'
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'gemerald_beanstalk/version'
|
3
|
+
require 'thread_safe'
|
4
|
+
require 'gemerald_beanstalk/job'
|
5
|
+
require 'gemerald_beanstalk/beanstalk'
|
6
|
+
require 'gemerald_beanstalk/connection'
|
7
|
+
require 'gemerald_beanstalk/command'
|
8
|
+
require 'gemerald_beanstalk/jobs'
|
9
|
+
require 'gemerald_beanstalk/tube'
|
10
|
+
require 'gemerald_beanstalk/server'
|
@@ -0,0 +1,289 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'socket'
|
3
|
+
require 'gemerald_beanstalk/beanstalk_helper'
|
4
|
+
|
5
|
+
class GemeraldBeanstalk::Beanstalk
|
6
|
+
|
7
|
+
# contains functionality supporting core commands
|
8
|
+
include GemeraldBeanstalk::BeanstalkHelper
|
9
|
+
|
10
|
+
# Colon-separated host and port of the Server the Beanstalk instance is
|
11
|
+
# running on.
|
12
|
+
attr_reader :address
|
13
|
+
|
14
|
+
# The maximum size in bytes that a job can be. Jobs exceeding this threshold
|
15
|
+
# will result in JOB_TOO_BIG responses.
|
16
|
+
attr_reader :max_job_size
|
17
|
+
|
18
|
+
|
19
|
+
# Initializes a new Beanstalk instance with the given +address+ and
|
20
|
+
# +maximum_job_size+. +address+ is a string identifying the host and port
|
21
|
+
# that the Beanstalk instance is running on. +maximum_job_size+ is the
|
22
|
+
# maximum size in bytes that a job can be. Jobs exceeding this threshold will
|
23
|
+
# result in JOB_TOO_BIG responses.
|
24
|
+
#
|
25
|
+
# beanstalk = GemeraldBeanstalk::Beanstalk.new('localhost:11300')
|
26
|
+
def initialize(address, maximum_job_size = 2**16)
|
27
|
+
@max_job_size = maximum_job_size
|
28
|
+
@address = address
|
29
|
+
@connections = ThreadSafe::Array.new
|
30
|
+
@delayed = ThreadSafe::Array.new
|
31
|
+
@id = SecureRandom.base64(16)
|
32
|
+
@jobs = GemeraldBeanstalk::Jobs.new
|
33
|
+
@mutex = Mutex.new
|
34
|
+
@paused = ThreadSafe::Array.new
|
35
|
+
@reserved = ThreadSafe::Cache.new {|reserved, key| reserved[key] = [] }
|
36
|
+
@stats = ThreadSafe::Hash.new(0)
|
37
|
+
@tubes = ThreadSafe::Cache.new
|
38
|
+
@up_at = Time.now.to_f
|
39
|
+
|
40
|
+
tube('default', :create_if_missing)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def bury(connection, job_id, priority, *args)
|
47
|
+
adjust_stats_key(:'cmd-bury')
|
48
|
+
job = find_job(job_id, :only => JOB_RESERVED_STATES)
|
49
|
+
return NOT_FOUND if job.nil? || !job.bury(connection, priority)
|
50
|
+
|
51
|
+
@reserved[connection].delete(job)
|
52
|
+
return BURIED
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def delete(connection, job_id = nil, *args)
|
57
|
+
adjust_stats_key(:'cmd-delete')
|
58
|
+
job = find_job(job_id)
|
59
|
+
return NOT_FOUND if job.nil?
|
60
|
+
|
61
|
+
original_state = job.state
|
62
|
+
return NOT_FOUND unless job.delete(connection)
|
63
|
+
|
64
|
+
tube(job.tube_name).delete(job)
|
65
|
+
@jobs[job.id - 1] = nil
|
66
|
+
@reserved[connection].delete(job) if JOB_RESERVED_STATES.include?(original_state)
|
67
|
+
|
68
|
+
return DELETED
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def ignore(connection, tube_name)
|
73
|
+
adjust_stats_key(:'cmd-ignore')
|
74
|
+
return NOT_IGNORED if (watched_count = connection.ignore(tube_name)).nil?
|
75
|
+
tube = tube(tube_name)
|
76
|
+
tube.ignore unless tube.nil?
|
77
|
+
return "WATCHING #{watched_count}\r\n"
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
def kick(connection, limit, *args)
|
82
|
+
adjust_stats_key(:'cmd-kick')
|
83
|
+
limit = limit.to_i
|
84
|
+
kicked = 0
|
85
|
+
JOB_INACTIVE_STATES.each do |job_state|
|
86
|
+
# GTE to handle negative limits
|
87
|
+
break if kicked >= limit
|
88
|
+
until (job = tube(connection.tube_used).next_job(job_state, :peek)).nil?
|
89
|
+
kicked += 1 if job.kick
|
90
|
+
break if kicked == limit
|
91
|
+
end
|
92
|
+
break if kicked > 0
|
93
|
+
end
|
94
|
+
|
95
|
+
return "KICKED #{kicked}\r\n"
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def kick_job(connection, job_id = nil, *args)
|
100
|
+
job = find_job(job_id, :only => JOB_INACTIVE_STATES)
|
101
|
+
return (!job.nil? && job.kick) ? KICKED : NOT_FOUND
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
def list_tubes(connection)
|
106
|
+
adjust_stats_key(:'cmd-list-tubes')
|
107
|
+
return tube_list(active_tubes.keys)
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
def list_tube_used(connection)
|
112
|
+
adjust_stats_key(:'cmd-list-tube-used')
|
113
|
+
return "USING #{connection.tube_used}\r\n"
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
def list_tubes_watched(connection)
|
118
|
+
adjust_stats_key(:'cmd-list-tubes-watched')
|
119
|
+
return tube_list(connection.tubes_watched)
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def pause_tube(connection, tube_name, delay)
|
124
|
+
adjust_stats_key(:'cmd-paue-tube')
|
125
|
+
return NOT_FOUND if (tube = tube(tube_name)).nil?
|
126
|
+
tube.pause(delay.to_i % 2**32)
|
127
|
+
@paused << tube
|
128
|
+
return PAUSED
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
def peek(connection, job_id = nil, *args)
|
133
|
+
adjust_stats_key(:'cmd-peek')
|
134
|
+
return peek_message(find_job(job_id))
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def peek_buried(connection)
|
139
|
+
return peek_by_state(connection, :buried)
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def peek_delayed(connection)
|
144
|
+
return peek_by_state(connection, :delayed)
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
def peek_ready(connection)
|
149
|
+
return peek_by_state(connection, :ready)
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
def put(connection, priority, delay, ttr, bytes, body)
|
154
|
+
adjust_stats_key(:'cmd-put')
|
155
|
+
bytes = bytes.to_i
|
156
|
+
return JOB_TOO_BIG if bytes > @max_job_size
|
157
|
+
return EXPECTED_CRLF if body.slice!(-2, 2) != CRLF || body.length != bytes
|
158
|
+
|
159
|
+
job = nil
|
160
|
+
# Ensure job insertion order and ID
|
161
|
+
@mutex.synchronize do
|
162
|
+
job = GemeraldBeanstalk::Job.new(self, @jobs.next_id, connection.tube_used, priority, delay, ttr, bytes, body)
|
163
|
+
@jobs.enqueue(job)
|
164
|
+
tube(connection.tube_used).put(job)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Send async so client doesn't wait while we check if job can be immediately dispatched
|
168
|
+
connection.transmit("INSERTED #{job.id}\r\n")
|
169
|
+
|
170
|
+
connection.producer = true
|
171
|
+
|
172
|
+
case job.state
|
173
|
+
when :ready
|
174
|
+
honor_reservations(job)
|
175
|
+
when :delayed
|
176
|
+
@delayed << job
|
177
|
+
end
|
178
|
+
return nil
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
def quit(connection)
|
183
|
+
disconnect(connection)
|
184
|
+
return nil
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def release(connection, job_id, priority, delay)
|
189
|
+
adjust_stats_key(:'cmd-release')
|
190
|
+
job = find_job(job_id, :only => JOB_RESERVED_STATES)
|
191
|
+
return NOT_FOUND if job.nil? || !job.release(connection, priority, delay)
|
192
|
+
|
193
|
+
@reserved[connection].delete(job)
|
194
|
+
@delayed << job if job.delayed?
|
195
|
+
return RELEASED
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
def reserve(connection, *args)
|
200
|
+
adjust_stats_key(:'cmd-reserve')
|
201
|
+
return BAD_FORMAT unless args.empty?
|
202
|
+
reserve_job(connection)
|
203
|
+
return nil
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
def reserve_with_timeout(connection, timeout = 0, *args)
|
208
|
+
adjust_stats_key(:'cmd-reserve-with-timeout')
|
209
|
+
timeout = timeout.to_i
|
210
|
+
return nil if reserve_job(connection, timeout) || timeout != 0
|
211
|
+
connection.wait_timed_out
|
212
|
+
return TIMED_OUT
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
def stats(connection)
|
217
|
+
adjust_stats_key(:'cmd-stats')
|
218
|
+
stats = @jobs.counts_by_state.merge(stats_commands).merge({
|
219
|
+
'job-timeouts' => @stats[:'job-timeouts'],
|
220
|
+
'total-jobs' => @jobs.total_jobs,
|
221
|
+
'max-job-size' => @max_job_size,
|
222
|
+
'current-tubes' => active_tubes.length,
|
223
|
+
}).merge(stats_connections).merge({
|
224
|
+
'pid' => Process.pid,
|
225
|
+
'version' => GemeraldBeanstalk::VERSION,
|
226
|
+
'rusage-utime' => 0,
|
227
|
+
'rusage-stime' => 0,
|
228
|
+
'uptime' => uptime,
|
229
|
+
'binlog-oldest-index' => 0,
|
230
|
+
'binlog-current-index' => 0,
|
231
|
+
'binlog-records-migrated' => 0,
|
232
|
+
'binlog-records-written' => 0,
|
233
|
+
'binlog-max-size' => 10485760,
|
234
|
+
'id' => @id,
|
235
|
+
'hostname' => Socket.gethostname,
|
236
|
+
})
|
237
|
+
return yaml_response(stats.map{|stat, value| "#{stat}: #{value}" })
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
def stats_job(connection, job_id = nil, *args)
|
242
|
+
adjust_stats_key(:'cmd-stats-job')
|
243
|
+
job = find_job(job_id)
|
244
|
+
return NOT_FOUND if job.nil?
|
245
|
+
|
246
|
+
return yaml_response(job.stats.map{ |stat, value| "#{stat}: #{value}" })
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
def stats_tube(connection, tube_name)
|
251
|
+
adjust_stats_key(:'cmd-stats-tube')
|
252
|
+
return NOT_FOUND if (tube = tube(tube_name)).nil?
|
253
|
+
|
254
|
+
return yaml_response(tube.stats.map{ |stat, value| "#{stat}: #{value}" })
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
def touch(connection, job_id = nil, *args)
|
259
|
+
adjust_stats_key(:'cmd-touch')
|
260
|
+
job = find_job(job_id, :only => JOB_RESERVED_STATES)
|
261
|
+
return NOT_FOUND if job.nil? || !job.touch(connection)
|
262
|
+
|
263
|
+
return TOUCHED
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
def use(connection, tube_name)
|
268
|
+
adjust_stats_key(:'cmd-use')
|
269
|
+
tube(connection.tube_used).stop_use
|
270
|
+
tube(tube_name, :create_if_missing).use
|
271
|
+
connection.use(tube_name)
|
272
|
+
|
273
|
+
return "USING #{tube_name}\r\n"
|
274
|
+
end
|
275
|
+
|
276
|
+
|
277
|
+
def watch(connection, tube_name)
|
278
|
+
adjust_stats_key(:'cmd-watch')
|
279
|
+
if connection.tubes_watched.include?(tube_name)
|
280
|
+
watched_count = connection.tubes_watched.length
|
281
|
+
else
|
282
|
+
tube(tube_name, :create_if_missing).watch
|
283
|
+
watched_count = connection.watch(tube_name)
|
284
|
+
end
|
285
|
+
|
286
|
+
return "WATCHING #{watched_count}\r\n"
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|