stalk_climber 0.0.2 → 0.0.3
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/lib/stalk_climber/climber.rb +47 -2
- data/lib/stalk_climber/connection.rb +83 -57
- data/lib/stalk_climber/job.rb +4 -2
- data/lib/stalk_climber/version.rb +1 -1
- data/test/unit/climber_test.rb +81 -1
- data/test/unit/connection_test.rb +67 -24
- data/test/unit/job_test.rb +4 -4
- metadata +3 -2
@@ -15,9 +15,30 @@ module StalkClimber
|
|
15
15
|
end
|
16
16
|
|
17
17
|
|
18
|
+
# Climb over all jobs on all connections in the connection pool.
|
19
|
+
# An instance of Job is yielded. For more information see Connection#climb
|
20
|
+
def climb
|
21
|
+
enum = to_enum
|
22
|
+
return enum unless block_given?
|
23
|
+
loop do
|
24
|
+
begin
|
25
|
+
yield enum.next
|
26
|
+
rescue StopIteration
|
27
|
+
return ($ERROR_INFO.nil? || $ERROR_INFO.result.nil?) ? nil : $ERROR_INFO.result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
alias_method :each, :climb
|
32
|
+
|
33
|
+
|
18
34
|
# Perform a threaded climb across all connections in the connection pool.
|
35
|
+
# This method cannot be used for enumerable enumeration because a break
|
36
|
+
# called from one of the threads will cause a LocalJumpError. This could be
|
37
|
+
# fixed, but expected behavior on break varies as to whether or not to wait
|
38
|
+
# for all threads before returning a result. However, still useful for
|
39
|
+
# operations that always visit all jobs.
|
19
40
|
# An instance of Job is yielded to +block+
|
20
|
-
def
|
41
|
+
def climb_threaded(&block)
|
21
42
|
threads = []
|
22
43
|
self.connection_pool.connections.each do |connection|
|
23
44
|
threads << Thread.new { connection.each(&block) }
|
@@ -25,7 +46,7 @@ module StalkClimber
|
|
25
46
|
threads.each(&:join)
|
26
47
|
return
|
27
48
|
end
|
28
|
-
alias_method :
|
49
|
+
alias_method :each_threaded, :climb_threaded
|
29
50
|
|
30
51
|
|
31
52
|
# Creates a new Climber instance, optionally yielding the instance
|
@@ -36,5 +57,29 @@ module StalkClimber
|
|
36
57
|
yield(self) if block_given?
|
37
58
|
end
|
38
59
|
|
60
|
+
|
61
|
+
# Returns a hash with connections as keys and max_job_ids as values
|
62
|
+
def max_job_ids
|
63
|
+
connection_pairs = connection_pool.connections.map do |connection|
|
64
|
+
[connection, connection.max_job_id]
|
65
|
+
end
|
66
|
+
return Hash[connection_pairs]
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# Returns an Enumerator for enumerating jobs on all connections.
|
71
|
+
# Connections are enumerated in the order defined. See Connection#to_enum
|
72
|
+
# for more information
|
73
|
+
# A job is yielded with each iteration.
|
74
|
+
def to_enum
|
75
|
+
return Enumerator.new do |yielder|
|
76
|
+
self.connection_pool.connections.each do |connection|
|
77
|
+
connection.each do |job|
|
78
|
+
yielder << job
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
39
84
|
end
|
40
85
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module StalkClimber
|
2
2
|
class Connection < Beaneater::Connection
|
3
|
-
include LazyEnumerable
|
3
|
+
include RUBY_VERSION >= '2.0.0' ? LazyEnumerable : Enumerable
|
4
4
|
|
5
5
|
DEFAULT_TUBE = 'stalk_climber'
|
6
6
|
PROBE_TRANSMISSION = "put 4294967295 0 300 2\r\n{}"
|
@@ -22,15 +22,57 @@ module StalkClimber
|
|
22
22
|
end
|
23
23
|
|
24
24
|
|
25
|
-
#
|
26
|
-
# each existing job on the beanstalk server. Jobs are enumerated in three phases. Jobs
|
27
|
-
# max_job_id and the max_climbed_job_id are pulled from beanstalk, cached, and
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
25
|
+
# Interface for job enumerator/enumeration in descending ID order. Returns an instance of
|
26
|
+
# Job for each existing job on the beanstalk server. Jobs are enumerated in three phases. Jobs
|
27
|
+
# between max_job_id and the max_climbed_job_id are pulled from beanstalk, cached, and yielded.
|
28
|
+
# Jobs that have already been cached are yielded if they still exist, otherwise they are deleted
|
29
|
+
# from the cache. Finally, jobs between min_climbed_job_id and 1 are pulled from beanstalk, cached,
|
30
|
+
# and yielded.
|
31
31
|
# Connection#each fulfills Enumberable contract, allowing connection to behave as an Enumerable.
|
32
|
-
def
|
33
|
-
|
32
|
+
def climb
|
33
|
+
enum = to_enum
|
34
|
+
return enum unless block_given?
|
35
|
+
loop do
|
36
|
+
begin
|
37
|
+
yield enum.next
|
38
|
+
rescue StopIteration
|
39
|
+
return ($ERROR_INFO.nil? || $ERROR_INFO.result.nil?) ? nil : $ERROR_INFO.result
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
alias_method :each, :climb
|
44
|
+
|
45
|
+
|
46
|
+
# Safe form of fetch_job!, returns a Job instance for the specified +job_id+.
|
47
|
+
# If the job does not exist, the error is caught and nil is passed returned instead.
|
48
|
+
def fetch_job(job_id)
|
49
|
+
begin
|
50
|
+
job = fetch_job!(job_id)
|
51
|
+
rescue Beaneater::NotFoundError
|
52
|
+
job = nil
|
53
|
+
end
|
54
|
+
return job
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Returns a Job instance for the specified +job_id+. If the job does not exist,
|
59
|
+
# a Beaneater::NotFoundError will bubble up from Beaneater. The job is not cached.
|
60
|
+
def fetch_job!(job_id)
|
61
|
+
return Job.new(transmit("peek #{job_id}"))
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Like fetch_job, but fetches all job ids in +job_ids+. Jobs are not cached and
|
66
|
+
# nil is returned if any of the jobs don't exist.
|
67
|
+
def fetch_jobs(*job_ids)
|
68
|
+
return job_ids.flatten.map { |job_id| fetch_job(job_id) }
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# Similar to fetch_job!, but fetches all job ids in +job_ids+. Jobs are not cached
|
73
|
+
# and a Beaneater::NotFoundError is raised if any of the listed jobs don't exist.
|
74
|
+
def fetch_jobs!(*job_ids)
|
75
|
+
return job_ids.flatten.map { |job_id| fetch_job!(job_id) }
|
34
76
|
end
|
35
77
|
|
36
78
|
|
@@ -68,63 +110,47 @@ module StalkClimber
|
|
68
110
|
end
|
69
111
|
|
70
112
|
|
71
|
-
#
|
72
|
-
#
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
rescue Beaneater::NotFoundError
|
77
|
-
block.call(nil)
|
78
|
-
end
|
79
|
-
end
|
113
|
+
# Returns an Enumerator for crawling all existing jobs for a connection.
|
114
|
+
# See Connection#each for more information.
|
115
|
+
def to_enum
|
116
|
+
return Enumerator.new do |yielder|
|
117
|
+
max_id = max_job_id
|
80
118
|
|
119
|
+
initial_cached_jobs = cache.values_at(*cache.keys.sort.reverse)
|
81
120
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
block.call(job)
|
87
|
-
end
|
88
|
-
|
121
|
+
max_id.downto(self.max_climbed_job_id + 1) do |job_id|
|
122
|
+
job = fetch_and_cache_job(job_id)
|
123
|
+
yielder << job unless job.nil?
|
124
|
+
end
|
89
125
|
|
90
|
-
|
126
|
+
initial_cached_jobs.each do |job|
|
127
|
+
if job.exists?
|
128
|
+
yielder << job
|
129
|
+
else
|
130
|
+
self.cache.delete(job.id)
|
131
|
+
end
|
132
|
+
end
|
91
133
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
def cache_job_and_yield(job_id, &block)
|
97
|
-
with_job(job_id) do |job|
|
98
|
-
self.cache[job_id] = job unless job.nil?
|
99
|
-
@min_climbed_job_id = job_id if job_id < @min_climbed_job_id
|
100
|
-
@max_climbed_job_id = job_id if job_id > @max_climbed_job_id
|
101
|
-
yield(job) unless job.nil?
|
134
|
+
([self.min_climbed_job_id - 1, max_id].min).downto(1) do |job_id|
|
135
|
+
job = fetch_and_cache_job(job_id)
|
136
|
+
yielder << job unless job.nil?
|
137
|
+
end
|
102
138
|
end
|
103
139
|
end
|
104
140
|
|
105
141
|
|
106
|
-
|
107
|
-
def climb(&block)
|
108
|
-
max_id = max_job_id
|
109
|
-
|
110
|
-
initial_cached_jobs = cache.values_at(*cache.keys.sort.reverse)
|
111
|
-
|
112
|
-
max_id.downto(self.max_climbed_job_id + 1) do |job_id|
|
113
|
-
cache_job_and_yield(job_id, &block)
|
114
|
-
end
|
115
|
-
|
116
|
-
initial_cached_jobs.each do |job|
|
117
|
-
if job.exists?
|
118
|
-
yield job
|
119
|
-
else
|
120
|
-
self.cache.delete(job.id)
|
121
|
-
end
|
122
|
-
end
|
142
|
+
protected
|
123
143
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
144
|
+
# Helper method, similar to fetch_job, that retrieves the job identified by
|
145
|
+
# +job_id+, caches it, and updates counters before returning the job.
|
146
|
+
# If the job does not exist, nothing is cached, however counters will be updated,
|
147
|
+
# and nil is returned
|
148
|
+
def fetch_and_cache_job(job_id)
|
149
|
+
job = fetch_job(job_id)
|
150
|
+
self.cache[job_id] = job unless job.nil?
|
151
|
+
@min_climbed_job_id = job_id if job_id < @min_climbed_job_id
|
152
|
+
@max_climbed_job_id = job_id if job_id > @max_climbed_job_id
|
153
|
+
return job
|
128
154
|
end
|
129
155
|
|
130
156
|
|
data/lib/stalk_climber/job.rb
CHANGED
@@ -15,7 +15,7 @@ module StalkClimber
|
|
15
15
|
|
16
16
|
# Returns or fetches the body of the job obtained via the peek command
|
17
17
|
def body
|
18
|
-
return @body ||=
|
18
|
+
return @body ||= connection.transmit("peek #{id}")[:body]
|
19
19
|
end
|
20
20
|
|
21
21
|
|
@@ -28,6 +28,7 @@ module StalkClimber
|
|
28
28
|
# Deletes the job from beanstalk. If the job is not found it is assumed that it
|
29
29
|
# has already been otherwise deleted.
|
30
30
|
def delete
|
31
|
+
return true if @status == 'DELETED'
|
31
32
|
begin
|
32
33
|
@connection.transmit("delete #{id}")
|
33
34
|
rescue Beaneater::NotFoundError
|
@@ -45,6 +46,7 @@ module StalkClimber
|
|
45
46
|
# the job, the peek command could return a much larger response. Rather than waste
|
46
47
|
# the trip to the server, stats are updated each time the method is called.
|
47
48
|
def exists?
|
49
|
+
return false if @status == 'DELETED'
|
48
50
|
begin
|
49
51
|
stats(:force_refresh)
|
50
52
|
return true
|
@@ -76,7 +78,7 @@ module StalkClimber
|
|
76
78
|
@body = @stats = nil
|
77
79
|
when 'FOUND' # peek
|
78
80
|
@id = job_data[:id].to_i
|
79
|
-
@body =
|
81
|
+
@body = job_data[:body]
|
80
82
|
@stats = nil
|
81
83
|
when 'OK' # stats-job
|
82
84
|
@body = nil
|
data/test/unit/climber_test.rb
CHANGED
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class ClimberTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
def
|
5
|
+
def test_each_caches_jobs_for_later_use
|
6
6
|
climber = StalkClimber::Climber.new(BEANSTALK_ADDRESSES)
|
7
7
|
|
8
8
|
test_jobs = {}
|
@@ -30,6 +30,35 @@ class ClimberTest < Test::Unit::TestCase
|
|
30
30
|
end
|
31
31
|
|
32
32
|
|
33
|
+
def test_each_threaded_works_for_non_break_situation
|
34
|
+
climber = StalkClimber::Climber.new(BEANSTALK_ADDRESSES)
|
35
|
+
test_jobs = {}
|
36
|
+
climber.connection_pool.connections.each do |connection|
|
37
|
+
test_jobs[connection.address] = []
|
38
|
+
5.times.to_a.map! do
|
39
|
+
test_jobs[connection.address] << StalkClimber::Job.new(connection.transmit(StalkClimber::Connection::PROBE_TRANSMISSION))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
assert_raise LocalJumpError do
|
44
|
+
climber.each_threaded do |job|
|
45
|
+
break
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
assert_nothing_raised do
|
50
|
+
# test normal enumeration
|
51
|
+
climber.each_threaded do |job|
|
52
|
+
job
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
climber.connection_pool.connections.each do |connection|
|
57
|
+
test_jobs[connection.address].map(&:delete)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
33
62
|
def test_connection_pool_creates_a_connection_pool
|
34
63
|
climber = StalkClimber::Climber.new('beanstalk://localhost')
|
35
64
|
assert_kind_of StalkClimber::ConnectionPool, climber.connection_pool
|
@@ -44,6 +73,34 @@ class ClimberTest < Test::Unit::TestCase
|
|
44
73
|
end
|
45
74
|
|
46
75
|
|
76
|
+
def test_enumerable_works_correctly
|
77
|
+
climber = StalkClimber::Climber.new(BEANSTALK_ADDRESSES)
|
78
|
+
test_jobs = {}
|
79
|
+
climber.connection_pool.connections.each do |connection|
|
80
|
+
test_jobs[connection.address] = []
|
81
|
+
5.times.to_a.map! do
|
82
|
+
test_jobs[connection.address] << StalkClimber::Job.new(connection.transmit(StalkClimber::Connection::PROBE_TRANSMISSION))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
assert_nothing_raised do
|
87
|
+
# verify enumeration can be short circuited
|
88
|
+
climber.any? do |job|
|
89
|
+
true
|
90
|
+
end
|
91
|
+
|
92
|
+
# test normal enumeration
|
93
|
+
climber.all? do |job|
|
94
|
+
job
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
climber.connection_pool.connections.each do |connection|
|
99
|
+
test_jobs[connection.address].map(&:delete)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
47
104
|
def test_each_is_an_alias_for_climb
|
48
105
|
assert_equal(
|
49
106
|
StalkClimber::Climber.instance_method(:climb),
|
@@ -53,6 +110,29 @@ class ClimberTest < Test::Unit::TestCase
|
|
53
110
|
end
|
54
111
|
|
55
112
|
|
113
|
+
def test_each_threaded_is_an_alias_for_climb_threaded
|
114
|
+
assert_equal(
|
115
|
+
StalkClimber::Climber.instance_method(:climb_threaded),
|
116
|
+
StalkClimber::Climber.instance_method(:each_threaded),
|
117
|
+
'Expected StalkClimber::Climber#each_threaded to be an alias for StalkClimber::Climber#climb_threaded'
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
def test_max_job_ids_returns_the_correct_max_job_ids
|
123
|
+
climber = StalkClimber::Climber.new(BEANSTALK_ADDRESSES, 'test_tube')
|
124
|
+
max_ids = climber.max_job_ids
|
125
|
+
max_ids.each do |connection, max_id|
|
126
|
+
assert_equal connection.max_job_id - 1, max_id
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
def test_to_enum_returns_an_enumerator
|
132
|
+
assert_kind_of Enumerator, StalkClimber::Climber.new(BEANSTALK_ADDRESSES).to_enum
|
133
|
+
end
|
134
|
+
|
135
|
+
|
56
136
|
def test_with_a_test_tube
|
57
137
|
climber = StalkClimber::Climber.new(BEANSTALK_ADDRESSES, 'test_tube')
|
58
138
|
assert_equal 'test_tube', climber.test_tube
|
@@ -34,6 +34,19 @@ class ConnectionTest < Test::Unit::TestCase
|
|
34
34
|
end
|
35
35
|
|
36
36
|
|
37
|
+
def test_deleted_jobs_should_not_be_enumerated
|
38
|
+
seeds = seed_jobs
|
39
|
+
seeds.map(&:delete)
|
40
|
+
seed_ids = seeds.map(&:id)
|
41
|
+
|
42
|
+
deleted = @connection.detect do |job|
|
43
|
+
seed_ids.include?(job.id)
|
44
|
+
end
|
45
|
+
|
46
|
+
assert_nil deleted, "Deleted job found in enumeration: #{deleted}"
|
47
|
+
end
|
48
|
+
|
49
|
+
|
37
50
|
def test_each_caches_jobs_for_later_use
|
38
51
|
seeds = seed_jobs
|
39
52
|
|
@@ -113,12 +126,62 @@ class ConnectionTest < Test::Unit::TestCase
|
|
113
126
|
end
|
114
127
|
|
115
128
|
|
116
|
-
def
|
117
|
-
@connection.expects(:
|
129
|
+
def test_each_calls_to_enum
|
130
|
+
@connection.expects(:to_enum).returns(Enumerator.new { |yielder| yielder << 1 })
|
118
131
|
@connection.each {}
|
119
132
|
end
|
120
133
|
|
121
134
|
|
135
|
+
def test_fetch_job_returns_nil_or_the_requested_job_if_it_exists
|
136
|
+
assert_nothing_raised do
|
137
|
+
job = @connection.fetch_job(@connection.max_job_id)
|
138
|
+
assert_equal nil, job
|
139
|
+
end
|
140
|
+
|
141
|
+
probe = seed_jobs(1).first
|
142
|
+
assert_equal probe.id, @connection.fetch_job(probe.id).id
|
143
|
+
probe.delete
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
def test_fetch_job_bang_returns_requested_job_or_raises_an_error_if_job_does_not_exist
|
148
|
+
assert_raise Beaneater::NotFoundError do
|
149
|
+
@connection.fetch_job!(@connection.max_job_id)
|
150
|
+
end
|
151
|
+
|
152
|
+
probe = seed_jobs(1).first
|
153
|
+
assert_equal probe.id, @connection.fetch_job!(probe.id).id
|
154
|
+
probe.delete
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def test_fetch_jobs_returns_each_requested_job_or_nil
|
159
|
+
assert_nothing_raised do
|
160
|
+
jobs = @connection.fetch_jobs(@connection.max_job_id, @connection.max_job_id)
|
161
|
+
assert_equal [nil, nil], jobs
|
162
|
+
end
|
163
|
+
|
164
|
+
probes = seed_jobs(2)
|
165
|
+
probe_ids = probes.map(&:id)
|
166
|
+
assert_equal probe_ids, @connection.fetch_jobs(probe_ids).map(&:id)
|
167
|
+
probes.map(&:delete)
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
def test_fetch_jobs_bang_returns_requested_jobs_or_raises_an_error_if_any_job_does_not_exist
|
172
|
+
probes = seed_jobs(2)
|
173
|
+
|
174
|
+
probe_ids = probes.map(&:id)
|
175
|
+
assert_equal probe_ids, @connection.fetch_jobs!(probe_ids).map(&:id)
|
176
|
+
|
177
|
+
assert_raise Beaneater::NotFoundError do
|
178
|
+
@connection.fetch_jobs!(probe_ids.first, @connection.max_job_id, probe_ids.last)
|
179
|
+
end
|
180
|
+
|
181
|
+
probes.map(&:delete)
|
182
|
+
end
|
183
|
+
|
184
|
+
|
122
185
|
def test_max_job_id_returns_expected_max_job_id
|
123
186
|
initial_max = @connection.max_job_id
|
124
187
|
seed_jobs(3).map(&:delete)
|
@@ -181,28 +244,8 @@ class ConnectionTest < Test::Unit::TestCase
|
|
181
244
|
end
|
182
245
|
|
183
246
|
|
184
|
-
def
|
185
|
-
|
186
|
-
@connection.with_job(@connection.max_job_id) do |job|
|
187
|
-
assert_equal nil, job
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
probe = seed_jobs(1).first
|
192
|
-
@connection.with_job(probe.id) do |job|
|
193
|
-
assert_equal probe.id, job.id
|
194
|
-
end
|
195
|
-
probe.delete
|
196
|
-
end
|
197
|
-
|
198
|
-
|
199
|
-
def test_with_job_bang_does_not_execute_block_and_raises_error_if_job_does_not_exist
|
200
|
-
block = lambda {}
|
201
|
-
block.expects(:call).never
|
202
|
-
assert_raise Beaneater::NotFoundError do
|
203
|
-
Object.any_instance.expects(:yield).never
|
204
|
-
@connection.with_job!(@connection.max_job_id, &block)
|
205
|
-
end
|
247
|
+
def test_to_enum_returns_an_enumerator
|
248
|
+
assert_kind_of Enumerator, @connection.to_enum
|
206
249
|
end
|
207
250
|
|
208
251
|
end
|
data/test/unit/job_test.rb
CHANGED
@@ -9,11 +9,11 @@ class Job < Test::Unit::TestCase
|
|
9
9
|
end
|
10
10
|
|
11
11
|
|
12
|
-
def
|
13
|
-
body = {'test' => true}
|
12
|
+
def test_body_performs_peek_and_parses_json
|
13
|
+
body = {'test' => true}.to_json
|
14
14
|
|
15
15
|
@job.connection.expects(:transmit).returns({
|
16
|
-
:body => body
|
16
|
+
:body => body,
|
17
17
|
})
|
18
18
|
assert_equal body, @job.body
|
19
19
|
|
@@ -53,7 +53,7 @@ class Job < Test::Unit::TestCase
|
|
53
53
|
assert_equal @connection, job.connection
|
54
54
|
assert_equal @job.id, job.id
|
55
55
|
assert_equal 'FOUND', job.instance_variable_get(:@status)
|
56
|
-
assert_equal({}, job.body)
|
56
|
+
assert_equal('{}', job.body)
|
57
57
|
refute job.instance_variable_get(:@stats)
|
58
58
|
end
|
59
59
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stalk_climber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -117,3 +117,4 @@ test_files:
|
|
117
117
|
- test/unit/connection_pool_test.rb
|
118
118
|
- test/unit/connection_test.rb
|
119
119
|
- test/unit/job_test.rb
|
120
|
+
has_rdoc:
|