kestrel-client 0.5.3 → 0.5.7

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.3
1
+ 0.5.7
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{kestrel-client}
8
- s.version = "0.5.3"
8
+ s.version = "0.5.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Matt Freels", "Rael Dornfest"]
12
- s.date = %q{2010-10-05}
12
+ s.date = %q{2010-10-06}
13
13
  s.description = %q{Ruby client for the Kestrel queue server}
14
14
  s.email = %q{rael@twitter.com}
15
15
  s.extra_rdoc_files = [
@@ -34,9 +34,7 @@ class Kestrel::Client::Transactional < Kestrel::Client::Proxy
34
34
 
35
35
  # Returns job from the +key+ queue 1 - ERROR_PROCESSING_RATE
36
36
  # pct. of the time. Every so often, checks the error queue for
37
- # jobs and returns a retryable job. If either the error queue or
38
- # +key+ queue are empty, attempts to pull a job from the
39
- # alternate queue before giving up.
37
+ # jobs and returns a retryable job.
40
38
  #
41
39
  # ==== Returns
42
40
  # Job, possibly retryable, or nil
@@ -44,21 +42,27 @@ class Kestrel::Client::Transactional < Kestrel::Client::Proxy
44
42
  def get(key, opts = {})
45
43
  raise MultipleQueueException if current_queue && key != current_queue
46
44
 
47
- close_transaction(current_try == 1 ? key : "#{key}_errors")
45
+ close_last_transaction
48
46
 
49
- q1, q2 = (rand < @error_rate) ? [key + "_errors", key] : [key, key + "_errors"]
47
+ queue = read_from_error_queue? ? key + "_errors" : key
50
48
 
51
- if job = get_with_fallback(q1, q2, opts.merge(:close => true, :open => true))
52
- @current_queue = key
49
+ if job = client.get(queue, opts.merge(:open => true))
53
50
  @job = job.is_a?(RetryableJob) ? job : RetryableJob.new(0, job)
51
+ @last_read_queue = queue
52
+ @current_queue = key
54
53
  @job.job
55
- else
56
- @current_queue = @job = nil
57
54
  end
58
55
  end
59
56
 
60
57
  def current_try
61
- @job ? @job.retries + 1 : 1
58
+ @job.retries + 1
59
+ end
60
+
61
+ def close_last_transaction #:nodoc:
62
+ return unless @last_read_queue
63
+
64
+ client.get_from_last(@last_read_queue + "/close")
65
+ @last_read_queue = @current_queue = @job = nil
62
66
  end
63
67
 
64
68
  # Enqueues the current job on the error queue for later
@@ -66,41 +70,31 @@ class Kestrel::Client::Transactional < Kestrel::Client::Proxy
66
70
  # gives up entirely.
67
71
  #
68
72
  # ==== Returns
69
- # Boolean:: true if the job is retryable, false otherwise
73
+ # Boolean:: true if the job is enqueued in the retry queue, false otherwise
74
+ #
70
75
  #
71
76
  def retry(item = nil)
72
77
  job =
73
78
  if item
74
- current_retries = (@job ? @job.retries : 0)
79
+ current_retries = (@job ? @job.retries : 0)
75
80
  RetryableJob.new(current_retries, item)
76
81
  else
77
- @job
82
+ @job.dup
78
83
  end
79
84
 
80
85
  return unless job
81
86
 
82
87
  job.retries += 1
83
88
 
84
- if should_retry = job.retries < @max_retries
85
- client.set(current_queue + "_errors", job)
86
- end
87
-
88
- # close the transaction on the original queue if this is the first retry
89
- close_transaction(job.retries == 1 ? current_queue : "#{current_queue}_errors")
89
+ client.set(current_queue + "_errors", job) if job.retries < @max_retries
90
+ close_last_transaction
90
91
 
91
- should_retry
92
+ job.retries < @max_retries
92
93
  end
93
94
 
94
95
  private
95
96
 
96
- # If a get against the +primary+ queue is nil, falls back to the
97
- # +secondary+ queue.
98
- #
99
- def get_with_fallback(primary, secondary, opts) #:nodoc:
100
- client.get(primary, opts) || client.get(secondary, opts)
101
- end
102
-
103
- def close_transaction(key) #:nodoc:
104
- client.get_from_last("#{key}/close")
97
+ def read_from_error_queue?
98
+ rand < @error_rate
105
99
  end
106
100
  end
@@ -1,52 +1,111 @@
1
1
  require 'spec/spec_helper'
2
2
 
3
3
  describe "Kestrel::Client::Transactional" do
4
- describe "Instance Methods" do
5
- before do
6
- @raw_kestrel_client = Kestrel::Client.new(*Kestrel::Config.default)
7
- @kestrel = Kestrel::Client::Transactional.new(@raw_kestrel_client)
8
- stub(@kestrel).rand { 1 }
9
- @queue = "some_queue"
4
+ before do
5
+ @raw_kestrel_client = Kestrel::Client.new(*Kestrel::Config.default)
6
+ @kestrel = Kestrel::Client::Transactional.new(@raw_kestrel_client)
7
+ @queue = "some_queue"
8
+ end
9
+
10
+ describe "integration" do
11
+ def get_job
12
+ job = nil
13
+ job = @kestrel.get(@queue) until job
14
+ job
10
15
  end
11
16
 
12
- describe "#get" do
17
+ it "processes normal jobs" do
18
+ returns = [:mcguffin]
19
+ stub(@raw_kestrel_client).get(@queue, anything) { returns.shift }
20
+ stub(@raw_kestrel_client).get(@queue + "_errors", anything)
21
+ mock(@raw_kestrel_client).get_from_last(@queue + "/close")
13
22
 
14
- it "asks for a transaction" do
15
- mock(@raw_kestrel_client).get(@queue, :open => true, :close => true) { :mcguffin }
16
- @kestrel.get(@queue).should == :mcguffin
17
- end
23
+ get_job.should == :mcguffin
24
+ @kestrel.current_try.should == 1
25
+ @kestrel.get(@queue) # simulate next get run
26
+ end
18
27
 
19
- it "gets from the error queue ERROR_PROCESSING_RATE pct. of the time" do
20
- mock(@kestrel).rand { Kestrel::Client::Transactional::ERROR_PROCESSING_RATE - 0.05 }
21
- mock(@raw_kestrel_client).get(@queue + "_errors", anything) { :mcguffin }
22
- mock(@raw_kestrel_client).get(@queue, anything).never
23
- @kestrel.get(@queue).should == :mcguffin
28
+ it "processes successful retries" do
29
+ returns = [Kestrel::Client::Transactional::RetryableJob.new(1, :mcguffin)]
30
+ stub(@raw_kestrel_client).get(@queue + "_errors", anything) { returns.shift }
31
+ stub(@raw_kestrel_client).get(@queue, anything)
32
+ mock(@raw_kestrel_client).get_from_last(@queue + "_errors/close")
33
+
34
+ get_job.should == :mcguffin
35
+ @kestrel.current_try.should == 2
36
+ @kestrel.get(@queue) # simulate next get run
37
+ end
38
+
39
+ it "processes normal jobs that should retry" do
40
+ returns = [:mcguffin]
41
+ stub(@raw_kestrel_client).get(@queue, anything) { returns.shift }
42
+ stub(@raw_kestrel_client).get(@queue + "_errors", anything)
43
+ mock(@raw_kestrel_client).set(@queue + "_errors", anything) do |q,j|
44
+ j.retries.should == 1
45
+ j.job.should == :mcguffin
24
46
  end
47
+ mock(@raw_kestrel_client).get_from_last(@queue + "/close")
25
48
 
26
- it "falls through to the normal queue when error queue is empty" do
27
- mock(@kestrel).rand { Kestrel::Client::Transactional::ERROR_PROCESSING_RATE - 0.05 }
28
- mock(@raw_kestrel_client).get(@queue + "_errors", anything) { nil }
29
- mock(@raw_kestrel_client).get(@queue, anything) { :mcguffin }
30
- @kestrel.get(@queue).should == :mcguffin
49
+ get_job.should == :mcguffin
50
+ @kestrel.current_try.should == 1
51
+
52
+ @kestrel.retry
53
+ @kestrel.get(@queue) # simulate next get run
54
+ end
55
+
56
+ it "processes retries that should retry" do
57
+ returns = [Kestrel::Client::Transactional::RetryableJob.new(1, :mcguffin)]
58
+ stub(@raw_kestrel_client).get(@queue + "_errors", anything) { returns.shift }
59
+ stub(@raw_kestrel_client).get(@queue, anything)
60
+ mock(@raw_kestrel_client).set(@queue + "_errors", anything) do |q,j|
61
+ j.retries.should == 2
62
+ j.job.should == :mcguffin
31
63
  end
64
+ mock(@raw_kestrel_client).get_from_last(@queue + "_errors/close")
32
65
 
33
- it "gets from the normal queue most of the time" do
34
- mock(@kestrel).rand { Kestrel::Client::Transactional::ERROR_PROCESSING_RATE + 0.05 }
35
- mock(@raw_kestrel_client).get(@queue, anything) { :mcguffin }
36
- mock(@raw_kestrel_client).get(@queue + "_errors", anything).never
66
+ get_job.should == :mcguffin
67
+ @kestrel.current_try.should == 2
68
+
69
+ @kestrel.retry
70
+ @kestrel.get(@queue) # simulate next get run
71
+ end
72
+
73
+ it "processes retries that should give up" do
74
+ returns = [Kestrel::Client::Transactional::RetryableJob.new(Kestrel::Client::Transactional::DEFAULT_RETRIES - 1, :mcguffin)]
75
+ stub(@raw_kestrel_client).get(@queue + "_errors", anything) { returns.shift }
76
+ stub(@raw_kestrel_client).get(@queue, anything)
77
+ mock(@raw_kestrel_client).set.never
78
+ mock(@raw_kestrel_client).get_from_last(@queue + "_errors/close")
79
+
80
+ get_job.should == :mcguffin
81
+ @kestrel.current_try.should == Kestrel::Client::Transactional::DEFAULT_RETRIES
82
+
83
+ @kestrel.retry
84
+ @kestrel.get(@queue) # simulate next get run
85
+ end
86
+ end
87
+
88
+ describe "Instance Methods" do
89
+ before do
90
+ stub(@kestrel).rand { 1 }
91
+ end
92
+
93
+ describe "#get" do
94
+ it "asks for a transaction" do
95
+ mock(@raw_kestrel_client).get(@queue, :open => true) { :mcguffin }
37
96
  @kestrel.get(@queue).should == :mcguffin
38
97
  end
39
98
 
40
- it "falls through to the error queue when normal queue is empty" do
99
+ it "is nil when the primary queue is empty and selected" do
41
100
  mock(@kestrel).rand { Kestrel::Client::Transactional::ERROR_PROCESSING_RATE + 0.05 }
42
101
  mock(@raw_kestrel_client).get(@queue, anything) { nil }
43
- mock(@raw_kestrel_client).get(@queue + "_errors", anything) { :mcguffin }
44
- @kestrel.get(@queue).should == :mcguffin
102
+ mock(@raw_kestrel_client).get(@queue + "_errors", anything).never
103
+ @kestrel.get(@queue).should be_nil
45
104
  end
46
105
 
47
- it "is nil when both queues are empty" do
48
- mock(@kestrel).rand { Kestrel::Client::Transactional::ERROR_PROCESSING_RATE + 0.05 }
49
- mock(@raw_kestrel_client).get(@queue, anything) { nil }
106
+ it "is nil when the error queue is empty and selected" do
107
+ mock(@kestrel).rand { Kestrel::Client::Transactional::ERROR_PROCESSING_RATE - 0.05 }
108
+ mock(@raw_kestrel_client).get(@queue, anything).never
50
109
  mock(@raw_kestrel_client).get(@queue + "_errors", anything) { nil }
51
110
  @kestrel.get(@queue).should be_nil
52
111
  end
@@ -58,7 +117,6 @@ describe "Kestrel::Client::Transactional" do
58
117
  end
59
118
 
60
119
  @kestrel.get(@queue).should == :mcmuffin
61
- @kestrel.current_try.should == 2
62
120
  end
63
121
 
64
122
  it "closes an open transaction with no retries" do
@@ -90,29 +148,6 @@ describe "Kestrel::Client::Transactional" do
90
148
  end
91
149
  end
92
150
 
93
- describe "#current_try" do
94
-
95
- it "returns 1 if nothing has been gotten" do
96
- @kestrel.current_try.should == 1
97
- end
98
-
99
- it "returns 1 for jobs that have not been retried" do
100
- mock(@raw_kestrel_client).get(@queue, anything) { :mcguffin }
101
- @kestrel.get(@queue)
102
- @kestrel.current_try.should == 1
103
- end
104
-
105
- it "returns 1 plus the number of tries for a RetryableJob" do
106
- stub(@kestrel).rand { 0 }
107
- mock(@raw_kestrel_client).get(@queue + "_errors", anything) do
108
- Kestrel::Client::Transactional::RetryableJob.new(1, :mcmuffin)
109
- end
110
- @kestrel.get(@queue)
111
- @kestrel.current_try.should == 2
112
- end
113
-
114
- end
115
-
116
151
  describe "#retry" do
117
152
  before do
118
153
  stub(@raw_kestrel_client).get(@queue, anything) { :mcmuffin }
@@ -157,6 +192,7 @@ describe "Kestrel::Client::Transactional" do
157
192
  Kestrel::Client::Transactional::RetryableJob.new(Kestrel::Client::Transactional::DEFAULT_RETRIES - 1, :mcmuffin)
158
193
  end
159
194
  mock(@raw_kestrel_client).set(@queue + "_errors", anything).never
195
+ mock(@raw_kestrel_client).get_from_last(@queue + "_errors/close")
160
196
  @kestrel.get(@queue)
161
197
  @kestrel.retry.should be_false
162
198
  end
@@ -179,7 +215,46 @@ describe "Kestrel::Client::Transactional" do
179
215
  mock(@raw_kestrel_client).get_from_last(@queue + "_errors/close")
180
216
  @kestrel.retry
181
217
  end
218
+ end
219
+
220
+ describe "#read_from_error_queue?" do
221
+ it "returns the error queue ERROR_PROCESSING_RATE pct. of the time" do
222
+ mock(@kestrel).rand { Kestrel::Client::Transactional::ERROR_PROCESSING_RATE - 0.05 }
223
+ @kestrel.send(:read_from_error_queue?).should == true
224
+ end
225
+
226
+ it "returns the normal queue most of the time" do
227
+ mock(@kestrel).rand { Kestrel::Client::Transactional::ERROR_PROCESSING_RATE + 0.05 }
228
+ @kestrel.send(:read_from_error_queue?).should == false
229
+ end
230
+ end
231
+
232
+ describe "#close_last_transaction" do
233
+ it "does nothing if there is no last transaction" do
234
+ mock(@raw_kestrel_client).get_from_last(@queue + "/close").never
235
+ mock(@raw_kestrel_client).get_from_last(@queue + "_errors/close").never
236
+ @kestrel.send(:close_last_transaction)
237
+ end
182
238
 
239
+ it "closes the normal queue if the job was pulled off of the normal queue" do
240
+ mock(@kestrel).read_from_error_queue? { false }
241
+ mock(@raw_kestrel_client).get(@queue, :open => true) { :mcguffin }
242
+ mock(@raw_kestrel_client).get_from_last(@queue + "/close")
243
+ mock(@raw_kestrel_client).get_from_last(@queue + "_errors/close").never
244
+
245
+ @kestrel.get(@queue).should == :mcguffin
246
+ @kestrel.send(:close_last_transaction)
247
+ end
248
+
249
+ it "closes the error queue if the job was pulled off of the error queue" do
250
+ mock(@kestrel).read_from_error_queue? { true }
251
+ mock(@raw_kestrel_client).get(@queue + "_errors", anything) { Kestrel::Client::Transactional::RetryableJob.new 1, :mcguffin }
252
+ mock(@raw_kestrel_client).get_from_last(@queue + "/close").never
253
+ mock(@raw_kestrel_client).get_from_last(@queue + "_errors/close")
254
+
255
+ @kestrel.get(@queue).should == :mcguffin
256
+ @kestrel.send(:close_last_transaction)
257
+ end
183
258
  end
184
259
  end
185
260
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kestrel-client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 5
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 5
9
- - 3
10
- version: 0.5.3
9
+ - 7
10
+ version: 0.5.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matt Freels
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-10-05 00:00:00 -07:00
19
+ date: 2010-10-06 00:00:00 -07:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency