resque-cleaner 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.2.3 (2011-04-11)
2
+
3
+ * Exception filter.
4
+
1
5
  ## 0.2.2 (2011-04-07)
2
6
 
3
7
  * Changed a way to load yajl/json\_gem.
data/README.markdown CHANGED
@@ -64,10 +64,18 @@ You could also group them by class.
64
64
  total: 10
65
65
  => {'BadJob' => 3, ...}
66
66
 
67
+ Or you could also group them by exception.
68
+
69
+ > cleaner.stats_by_exception
70
+ RuntimeError: 35
71
+ SyntaxError: 7
72
+ total: 42
73
+ => {'RuntimeError' => 35, ...}
74
+
67
75
  You can get the ones filtered with a block: it targets only jobs which the block
68
- evaluetes true.
76
+ evaluates true.
69
77
 
70
- e.g. Show stats only of jobs entried with some arguments:
78
+ e.g. Show stats only of jobs entered with some arguments:
71
79
 
72
80
  > cleaner.stats_by_date {|j| j["payload"]["args"].size > 0}
73
81
  2009/03/13: 3
@@ -90,13 +98,13 @@ e.g. Retry only jobs with some arguments:
90
98
  > cleaner.requeue {|j| j["payload"]["args"].size > 0}
91
99
 
92
100
  The job hash is extended with a module which defines some useful methods. You
93
- can use it in the blcok.
101
+ can use it in the block.
94
102
 
95
- e.g. Retry only jobs entried within a day:
103
+ e.g. Retry only jobs entered within a day:
96
104
 
97
105
  > cleaner.requeue {|j| j.after?(1.day.ago)}
98
106
 
99
- e.g. Retry EmailJob entried with arguments within 3 days:
107
+ e.g. Retry EmailJob entered with arguments within 3 days:
100
108
 
101
109
  > cleaner.requeue {|j| j.after?(3.days.ago) && j.klass?(EmailJob) && j["payload"]["args"].size>0}
102
110
 
@@ -112,7 +120,7 @@ You can clear all failed jobs with this method:
112
120
 
113
121
  > cleaner.clear
114
122
 
115
- Like you can do with the retry method, the clear metod takes a block. Here are
123
+ Like you can do with the retry method, the clear method takes a block. Here are
116
124
  some examples:
117
125
 
118
126
  > cleaner.clear {|j| j.retried?}
@@ -121,7 +129,7 @@ some examples:
121
129
  > cleaner.clear {|j| j.queue?(:low) && j.before?('2010-10-10')}
122
130
  => clears all jobs entried in :low queue before 10th October, 2010.
123
131
 
124
- > cleaner.clear {|j| j["exception"]=="RuntimeError" && j.queue?(:low)}
132
+ > cleaner.clear {|j| j.exception?("RuntimeError") && j.queue?(:low)}
125
133
  => clears all jobs raised RuntimeError and queued :low queue
126
134
 
127
135
  **Retry and Clear Jobs**
@@ -136,7 +144,7 @@ e.g. Retry EmailJob and remove from failed jobs:
136
144
  **Retry with other queue**
137
145
 
138
146
  You can requeue failed jobs into other queue. In this way, you can retry failed
139
- jobs without blocking jobs being entried by your service running in the live.
147
+ jobs without blocking jobs being entered by your service running in the live.
140
148
 
141
149
  e.g. Retry failed jobs on :retry queue
142
150
 
@@ -150,13 +158,13 @@ Don't forget to launch resque worker for the queue.
150
158
 
151
159
  You can just select the jobs of course. Here are some examples:
152
160
 
153
- > cleaner.select {|j| j["exception"]=="RuntimeError"}
161
+ > cleaner.select {|j| j["payload"]["args"][0]=="Johonson"}
154
162
  > cleaner.select {|j| j.after?(2.days.ago)}
155
163
  > cleaner.select #=> returns all jobs
156
164
 
157
165
  **Helper Methods**
158
166
 
159
- Here is a list of methods a failed job ratained through ResqueCleaner has:
167
+ Here is a list of methods a failed job retained through ResqueCleaner has:
160
168
 
161
169
  retried?: returns true if the job has already been retried.
162
170
  requeued?: alias of retried?.
@@ -164,6 +172,7 @@ Here is a list of methods a failed job ratained through ResqueCleaner has:
164
172
  after?(time): returns true if the job failed after the time.
165
173
  klass?(klass_or_name): returns true if the class of job matches.
166
174
  queue?(queue_name): returns true if the queue of job matches.
175
+ exception?(exception_name): returns true if the exception matches.
167
176
 
168
177
 
169
178
  Failed Job
@@ -200,7 +209,7 @@ ResqueCleaner supposes recent jobs are more important than old jobs. Therefore
200
209
  ResqueCleaner deals with **ONLY LAST X(default=1000) JOBS**. In this way, you
201
210
  could avoid slow responses. You can change the number through `limiter` attribute.
202
211
 
203
- Let's see how it works with an follwing example.
212
+ Let's see how it works with an following example.
204
213
 
205
214
  **Sample Situation**
206
215
 
@@ -227,13 +236,13 @@ You can change the maximum number of the limiter with maximum attribute.
227
236
  > cleaner.limiter.on?
228
237
  => true
229
238
 
230
- With limiter, ResqueClener's filtering targets only the last X(3000 in this
231
- sampe) failed jobs.
239
+ With limiter, ResqueCleaner's filtering targets only the last X(3000 in this
240
+ sample) failed jobs.
232
241
 
233
242
  > cleaner.select.size
234
243
  => 3,000
235
244
 
236
- The clear\_stale method deletes all jobs entried prior to the last X(3000 in
245
+ The clear\_stale method deletes all jobs entered prior to the last X(3000 in
237
246
  this sample) failed jobs. This calls Redis API and no iteration occurs on Ruby
238
247
  application; it should be quick even if there are huge number of failed jobs.
239
248
 
@@ -245,4 +254,9 @@ application; it should be quick even if there are huge number of failed jobs.
245
254
  > cleaner.limiter.on?
246
255
  => false
247
256
 
257
+ Many Thanks!
258
+ ------------
259
+
260
+ To our [Contributors](https://github.com/ono/resque-cleaner/contributors)
261
+
248
262
 
@@ -46,7 +46,7 @@ module Resque
46
46
  end
47
47
 
48
48
  print_stats(stats) if print?
49
- stats
49
+ stats
50
50
  end
51
51
 
52
52
  # Stats by class.
@@ -59,7 +59,20 @@ module Resque
59
59
  end
60
60
 
61
61
  print_stats(stats) if print?
62
- stats
62
+ stats
63
+ end
64
+
65
+ # Stats by exception.
66
+ def stats_by_exception(&block)
67
+ jobs, stats = select(&block), {}
68
+ jobs.each do |job|
69
+ exception = job["exception"]
70
+ stats[exception] ||= 0
71
+ stats[exception] += 1
72
+ end
73
+
74
+ print_stats(stats) if print?
75
+ stats
63
76
  end
64
77
 
65
78
  # Print stats
@@ -161,6 +174,11 @@ module Resque
161
174
  self["payload"]["class"] == klass_or_name.to_s
162
175
  end
163
176
 
177
+ # Returns true if the exception raised by the failed job matches. Otherwise returns false.
178
+ def exception?(exception)
179
+ self["exception"] == exception.to_s
180
+ end
181
+
164
182
  # Returns true if the queue of the job matches. Otherwise returns false.
165
183
  def queue?(queue)
166
184
  self["queue"] == queue.to_s
@@ -168,7 +186,7 @@ module Resque
168
186
  end
169
187
 
170
188
  # Through the Limiter class, you accesses only the last x(default 1000)
171
- # jobs.
189
+ # jobs.
172
190
  class Limiter
173
191
  DEFAULT_MAX_JOBS = 1000
174
192
  attr_accessor :maximum
@@ -10,7 +10,7 @@ module ResqueCleaner
10
10
  File.join(File.dirname(__FILE__), 'server', 'public', filename)
11
11
  end
12
12
 
13
- # Pagination helpr for list page.
13
+ # Pagination helper for list page.
14
14
  class Paginate
15
15
  attr_accessor :page_size, :page, :jobs, :url
16
16
  def initialize(jobs, url, page=1, page_size=20)
@@ -87,6 +87,16 @@ module ResqueCleaner
87
87
  end
88
88
  html += "</select>"
89
89
  end
90
+
91
+ def exception_filter(id, name, exceptions, value)
92
+ html = "<select id=\"#{id}\" name=\"#{name}\">"
93
+ html += "<option value=\"\">-</option>"
94
+ exceptions.each do |ex|
95
+ selected = ex == value ? 'selected="selected"' : ''
96
+ html += "<option #{selected} value=\"#{ex}\">#{ex}</option>"
97
+ end
98
+ html += "</select>"
99
+ end
90
100
  end
91
101
 
92
102
  get "/cleaner" do
@@ -121,10 +131,11 @@ module ResqueCleaner
121
131
 
122
132
  @failed = cleaner.select(&block).reverse
123
133
 
124
- url = "cleaner_list?c=#{@klass}&f=#{@from}&t=#{@to}"
134
+ url = "cleaner_list?c=#{@klass}&ex=#{@exception}f=#{@from}&t=#{@to}"
125
135
  @paginate = Paginate.new(@failed, url, params[:p].to_i)
126
136
 
127
137
  @klasses = cleaner.stats_by_class.keys
138
+ @exceptions = cleaner.stats_by_exception.keys
128
139
  @count = cleaner.select(&block).size
129
140
 
130
141
  erb File.read(ResqueCleaner::Server.erb_path('cleaner_list.erb'))
@@ -141,14 +152,14 @@ module ResqueCleaner
141
152
 
142
153
  block = filter_block
143
154
 
144
- @count =
155
+ @count =
145
156
  case params[:action]
146
157
  when "clear" then cleaner.clear(&block)
147
158
  when "retry_and_clear" then cleaner.requeue(true,&block)
148
159
  when "retry" then cleaner.requeue(false,{},&block)
149
160
  end
150
161
 
151
- @url = "cleaner_list?c=#{@klass}&f=#{@from}&t=#{@to}"
162
+ @url = "cleaner_list?c=#{@klass}&ex=#{@exception}&f=#{@from}&t=#{@to}"
152
163
  erb File.read(ResqueCleaner::Server.erb_path('cleaner_exec.erb'))
153
164
  end
154
165
 
@@ -184,13 +195,15 @@ module ResqueCleaner
184
195
  @from = params[:f]=="" ? nil : params[:f]
185
196
  @to = params[:t]=="" ? nil : params[:t]
186
197
  @klass = params[:c]=="" ? nil : params[:c]
198
+ @exception = params[:ex]=="" ? nil : params[:ex]
187
199
  end
188
200
 
189
201
  def filter_block
190
202
  block = lambda{|j|
191
203
  (!@from || j.after?(hours_ago(@from))) &&
192
204
  (!@to || j.before?(hours_ago(@to))) &&
193
- (!@klass || j.klass?(@klass)) &&
205
+ (!@klass || j.klass?(@klass)) &&
206
+ (!@exception || j.exception?(@exception)) &&
194
207
  (!@sha1 || @sha1[Digest::SHA1.hexdigest(j.to_json)])
195
208
  }
196
209
  end
@@ -12,6 +12,9 @@
12
12
  <span class="class_filter">
13
13
  Class: <%= class_filter("filter_class","c",@klasses,@klass)%>
14
14
  </span>
15
+ <span class="exception_filter">
16
+ Exception: <%= exception_filter("filter_class","ex",@exceptions,@exception)%>
17
+ </span>
15
18
  <span class="time_filter">
16
19
  From: <%= time_filter("filter_from","f",@from)%>
17
20
  </span>
@@ -113,6 +113,10 @@ context "ResqueCleaner" do
113
113
  ret = @cleaner.select {|j| j.klass?(BadJobWithSyntaxError)}
114
114
  assert_equal 7, ret.size
115
115
 
116
+ # filter by exception
117
+ ret = @cleaner.select {|j| j.exception?(SyntaxError)}
118
+ assert_equal 7, ret.size
119
+
116
120
  # filter by queue
117
121
  ret = @cleaner.select {|j| j.queue?(:jobs2)}
118
122
  assert_equal 20, ret.size
@@ -149,6 +153,12 @@ context "ResqueCleaner" do
149
153
  assert_equal 7, ret['BadJobWithSyntaxError']
150
154
  end
151
155
 
156
+ test "#stats_by_exception returns stats grouped by exception" do
157
+ ret = @cleaner.stats_by_exception
158
+ assert_equal 35, ret['RuntimeError']
159
+ assert_equal 7, ret['SyntaxError']
160
+ end
161
+
152
162
  test "#lock ensures that a new failure job doesn't affect in a limit mode" do
153
163
  @cleaner.limiter.maximum = 23
154
164
  @cleaner.limiter.lock do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-cleaner
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 2
10
- version: 0.2.2
9
+ - 3
10
+ version: 0.2.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tatsuya Ono
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-07 00:00:00 +01:00
18
+ date: 2011-04-11 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency