resque-cleaner 0.2.10 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDVkZjMyNjQ1NTM5ZDEyOWEzMTNmY2QyN2ZiOWFhZTZjYmQ2ZjIzYQ==
5
+ data.tar.gz: !binary |-
6
+ ZDk3M2IxN2M2YTU3NDA2ZmZiOTVhMTFlNTU3NmVjOWJmYzQzNzA0Nw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NjEyZWM0MmQ1MDRhY2U2ZWQ3NzI3ODJjYTBhMTkwZDU5MGEzZjY4ZDg5ZmNk
10
+ NTgyMzZjMjJlZTJmZjU4OWM2MmZkNDkyY2QyMDVmOTQyMTBhYmExOTk3NWJj
11
+ ZTc2MWJkZWFjNjg3YjliMTc4YjVmNzMyNDliNjQ4YTU1NGYyMzc=
12
+ data.tar.gz: !binary |-
13
+ MDA5M2FkY2Q0ZmVjYmM2YTdkNjQ0YTE1MjhjMjhjMzZiOGI2YjY0NWRiN2Jh
14
+ MDRiMmU2NTdiMjA5NTgxNGEyOTQ3Mzc3OWVkYjg2NGYzZWUxN2U4YzgwOGU3
15
+ M2UyZDA5OWU0OTlhN2FlZjkzZGZhNDJjZTBlMThhNjEyM2IxZDU=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,38 @@
1
+ ## 0.4.1 (2018-01-25)
2
+
3
+ * Remove Requeue version lock (#46)
4
+
5
+ ## 0.4.0 (2017-11-20)
6
+
7
+ * Render CSS as ERB partial to make Rails 5 compatible (#45)
8
+
9
+ ## 0.3.2 (2016-03-09)
10
+
11
+ * Handle failure JSON with nil on payload safely (#40)
12
+
13
+ ## 0.3.1 (2016-01-28)
14
+
15
+ * Bug fix: fix the issue regex is not applied on bulk clearance (#36)
16
+
17
+ ## 0.3.0 (2014-05-27)
18
+
19
+ * Search by regex (#27)
20
+ * Show stats by exception (#29)
21
+ * Stop supporting ruby 1.8.x and 1.9.2
22
+ * Escape query parameters (#30)
23
+
24
+ ## 0.2.12 (2013-12-03)
25
+
26
+ * Remove Resque::Helpers include (#23)
27
+ * Tweak Gemspec (#24)
28
+ * Don't use yaml format to show arguments
29
+ * Tweak README
30
+
31
+ ## 0.2.11 (2013-07-19)
32
+
33
+ * Use transaction for retry-and-clear (#22).
34
+ * Fix for CI
35
+
1
36
  ## 0.2.10 (2012-10-15)
2
37
 
3
38
  * Bug fix: use URL helper to support resque-web which is not hosted under '/'.
@@ -1,4 +1,4 @@
1
- ResqueCleaner [![Travis-CI](https://secure.travis-ci.org/ono/resque-cleaner.png?branch=master)](http://travis-ci.org/ono/resque-cleaner) [![Dependency Status](https://gemnasium.com/ono/resque-cleaner.png)](https://gemnasium.com/ono/resque-cleaner)
1
+ ResqueCleaner
2
2
  =============
3
3
 
4
4
  [github.com/ono/resque-cleaner](https://github.com/ono/resque-cleaner)
@@ -27,7 +27,7 @@ Resque-Web integration
27
27
  ----------------------
28
28
 
29
29
  ![Screen 1](https://github.com/ono/resque-cleaner/raw/master/misc/resque-cleaner-main.png)
30
- ![Screen 2](https://github.com/ono/resque-cleaner/raw/master/misc/resque-cleaner-list.png)
30
+ ![Screen 2](misc/resque-cleaner-list-with-regex.png)
31
31
 
32
32
 
33
33
  Configuration
@@ -117,6 +117,13 @@ e.g. Show stats only of jobs entered with some arguments:
117
117
  => {'2009/03/10' => 3, ...}
118
118
  ```
119
119
 
120
+ A convenience helper for searching for failed jobs which satisfy a
121
+ regular expression:
122
+
123
+ ```ruby
124
+ cleaner.select_by_regex(/Jason/) # => all failed jobs that have "Jason" in them
125
+ ```
126
+
120
127
  **Retry(Requeue) Jobs**
121
128
 
122
129
  You can retry all failed jobs with this method.
@@ -0,0 +1,63 @@
1
+ <style type="text/css" media="screen">
2
+ #main .cleaner .title h1 { float: left }
3
+
4
+ #main .cleaner .sub_header {color: #888; font-size: 80%; font-weight: bold}
5
+
6
+ #main .cleaner .control_panel {
7
+ margin: 5px 0 10px; padding: 5px; background: #eee; display: inline-block;
8
+ -webkit-border-radius:5px; border:1px solid #ccc;
9
+ }
10
+
11
+ #main .cleaner #exec { color: black; }
12
+ #main .cleaner #exec select { margin-right: 20px }
13
+ #main .cleaner #exec a { margin-right: 5px}
14
+ #main .cleaner #exec a.disabled { color: #aaa}
15
+
16
+ #main .cleaner table.class_list { width: auto }
17
+ #main .cleaner td.number { text-align: right }
18
+ #main .cleaner tr.total { border-top: 3px double #ccc}
19
+
20
+ #main .cleaner form { float: none; margin: 0}
21
+
22
+ #main .cleaner .warning { margin: 30px 0; padding: 10px; background: #fdd; display: inline-block; }
23
+
24
+ #main .clearfix:after {
25
+ content: ".";
26
+ display: block;
27
+ height: 0;
28
+ clear: both;
29
+ visibility: hidden;
30
+ }
31
+ #main .cleaner ul.failed {
32
+ margin-bottom: 10px
33
+ }
34
+
35
+ #main .cleaner .list_info{
36
+ color: #999; text-align: center;
37
+ }
38
+ #main .cleaner .list_info a{
39
+ color: #666
40
+ }
41
+ #main .cleaner .list_info .list_summary{
42
+ vertical-align: baseline;
43
+ display: inline-block;
44
+ margin: 0; padding:0;
45
+ }
46
+ #main .cleaner ul.pagination {
47
+ display: inline-block;
48
+ vertical-align: baseline;
49
+ margin:0; padding:0;
50
+ }
51
+ #main .cleaner ul.pagination li {
52
+ list-style:none; float: left; padding: 0 3px;
53
+ }
54
+ #main .cleaner ul.pagination li.current {
55
+ color: #333; font-weight: bold;
56
+ }
57
+ #main .cleaner ul.pagination li.summary{
58
+ padding-right: 10px
59
+ }
60
+ #main .cleaner div.dump{
61
+ float: right
62
+ }
63
+ </style>
@@ -0,0 +1,44 @@
1
+ <table class="class_list">
2
+ <tr>
3
+ <th><%= type.gsub('klass','class').capitalize %></th>
4
+ <th>Failed</th>
5
+ <th>In last 1 hour</th>
6
+ <th>In last 3 hours</th>
7
+ <th>In last 24 hours</th>
8
+ <th>In last 3 days</th>
9
+ <th>In last 7 days</th>
10
+ </tr>
11
+ <% @stats[type.to_sym].each do |field,count| %>
12
+ <tr>
13
+ <% filter = "#{q}=#{URI.encode(field)}" %>
14
+ <td><%= field %></td>
15
+ <td class="number">
16
+ <a href="cleaner_list?<%=filter%>"><%= count[:total] %></a>
17
+ </td>
18
+ <td class="number">
19
+ <a href="cleaner_list?<%=filter%>&f=1"><%= count[:h1] %></a>
20
+ </td>
21
+ <td class="number">
22
+ <a href="cleaner_list?<%=filter%>&f=3"><%= count[:h3] %></a>
23
+ </td>
24
+ <td class="number">
25
+ <a href="cleaner_list?<%=filter%>&f=24"><%= count[:d1] %></a>
26
+ </td>
27
+ <td class="number">
28
+ <a href="cleaner_list?<%=filter%>&f=72"><%= count[:d3] %></a>
29
+ </td>
30
+ <td class="number">
31
+ <a href="cleaner_list?<%=filter%>&f=168"><%= count[:d7] %></a>
32
+ </td>
33
+ </tr>
34
+ <% end %>
35
+ <tr class="total">
36
+ <td>Total</td>
37
+ <td class="number"><a href="cleaner_list"><%= @total[:total] %></a></td>
38
+ <td class="number"><a href="cleaner_list?f=1"><%= @total[:h1] %></a></td>
39
+ <td class="number"><a href="cleaner_list?f=3"><%= @total[:h3] %></a></td>
40
+ <td class="number"><a href="cleaner_list?f=24"><%= @total[:d1] %></a></td>
41
+ <td class="number"><a href="cleaner_list?f=72"><%= @total[:d3] %></a></td>
42
+ <td class="number"><a href="cleaner_list?f=168"><%= @total[:d7] %></a></td>
43
+ </tr>
44
+ </table>
@@ -1,41 +1,23 @@
1
- <link href="cleaner/public/cleaner.css" media="screen" rel="stylesheet" type="text/css">
1
+ <%= erb File.read(ResqueCleaner::Server.erb_path("_cleaner_styles.erb")) %>
2
2
 
3
3
  <div class="cleaner">
4
4
  <div class="title clearfix">
5
- <h1>Job Classes Failed</h1>
5
+ <h1>Group by class</h1>
6
6
  </div>
7
7
 
8
- <table class="class_list">
9
- <tr>
10
- <th>Class</th>
11
- <th>Failed</th>
12
- <th>In last 1 hour</th>
13
- <th>In last 3 hours</th>
14
- <th>In last 24 hours</th>
15
- <th>In last 3 days</th>
16
- <th>In last 7 days</th>
17
- </tr>
18
- <% @stats.each do |klass,count| %>
19
- <tr>
20
- <td><%= klass %></td>
21
- <td class="number"><a href="cleaner_list?c=<%=klass%>"><%= count["total"] %></a></td>
22
- <td class="number"><a href="cleaner_list?c=<%=klass%>&f=1"><%= count["1h"] %></a></td>
23
- <td class="number"><a href="cleaner_list?c=<%=klass%>&f=3"><%= count["3h"] %></a></td>
24
- <td class="number"><a href="cleaner_list?c=<%=klass%>&f=24"><%= count["1d"] %></a></td>
25
- <td class="number"><a href="cleaner_list?c=<%=klass%>&f=72"><%= count["3d"] %></a></td>
26
- <td class="number"><a href="cleaner_list?c=<%=klass%>&f=168"><%= count["7d"] %></a></td>
27
- </tr>
28
- <% end %>
29
- <tr class="total">
30
- <td>Total</td>
31
- <td class="number"><a href="cleaner_list"><%= @total["total"] %></a></td>
32
- <td class="number"><a href="cleaner_list?f=1"><%= @total["1h"] %></a></td>
33
- <td class="number"><a href="cleaner_list?f=3"><%= @total["3h"] %></a></td>
34
- <td class="number"><a href="cleaner_list?f=24"><%= @total["1d"] %></a></td>
35
- <td class="number"><a href="cleaner_list?f=72"><%= @total["3d"] %></a></td>
36
- <td class="number"><a href="cleaner_list?f=168"><%= @total["7d"] %></a></td>
37
- </tr>
38
- </table>
8
+ <%= erb(
9
+ File.read(ResqueCleaner::Server.erb_path("_stats.erb")),
10
+ locals: {q: 'c', type: 'klass'}
11
+ ) %>
12
+
13
+ <div class="title clearfix">
14
+ <h1>Group by exception</h1>
15
+ </div>
16
+
17
+ <%= erb(
18
+ File.read(ResqueCleaner::Server.erb_path("_stats.erb")),
19
+ locals: {q: 'ex', type: 'exception'}
20
+ ) %>
39
21
 
40
22
  <% if @cleaner.limiter.on? %>
41
23
  <%= erb File.read(ResqueCleaner::Server.erb_path("_limiter.erb")) %>
@@ -1,8 +1,8 @@
1
- <link href="cleaner/public/cleaner.css" media="screen" rel="stylesheet" type="text/css">
1
+ <%= erb File.read(ResqueCleaner::Server.erb_path("_cleaner_styles.erb")) %>
2
2
 
3
3
  <div class="cleaner">
4
4
  <p class="message">Processed <%= @count %> jobs.</p>
5
5
  <p class="back_to_list">
6
- <a href="<%=@url%>">Back to List</a>
6
+ <a href="<%=@list_url%>">Back to List</a>
7
7
  </p>
8
8
  </div>
@@ -1,4 +1,4 @@
1
- <link href="cleaner/public/cleaner.css" media="screen" rel="stylesheet" type="text/css">
1
+ <%= erb File.read(ResqueCleaner::Server.erb_path("_cleaner_styles.erb")) %>
2
2
 
3
3
  <!-- Many code was copied from failed.erb of the original resque -->
4
4
  <div class="cleaner">
@@ -21,6 +21,9 @@
21
21
  <span class="time_filter">
22
22
  To: <%= time_filter("filter_to","t",@to)%>
23
23
  </span>
24
+ <span class="regex_filter">
25
+ Regex: <%= text_filter("filter_regex", "regex", Rack::Utils.escape_html(@regex))%>
26
+ </span>
24
27
  <input type="submit" value="Filter" />
25
28
  </form>
26
29
  </div>
@@ -35,6 +38,7 @@
35
38
  <input type="hidden" name="t" value="<%=@to%>" />
36
39
  <input type="hidden" name="p" value="<%=@paginate.page%>" />
37
40
  <input type="hidden" name="ex" value="<%=@exception%>" />
41
+ <input type="hidden" name="regex" value="<%=Rack::Utils.escape_html(@regex)%>" />
38
42
  <select id="form_action" name="action">
39
43
  <option id="default_option" value="" selected="selected">-- Select Action --</option>
40
44
  <option value="clear">Clear</option>
@@ -87,7 +91,7 @@
87
91
  <dt>Class</dt>
88
92
  <dd><code><%= job['payload'] ? job['payload']['class'] : 'nil' %></code></dd>
89
93
  <dt>Arguments</dt>
90
- <dd><pre><%=h job['payload'] ? show_args(job['payload']['args']) : 'nil' %></pre></dd>
94
+ <dd><pre><%=h job['payload'] ? show_job_args(job['payload']['args']) : 'nil' %></pre></dd>
91
95
  <dt>Exception</dt>
92
96
  <dd><code><%= job['exception'] %></code></dd>
93
97
  <dt>Error</dt>
@@ -1,3 +1,5 @@
1
+ require 'yaml'
2
+
1
3
  # Extends Resque Web Based UI.
2
4
  # Structure has been borrowed from ResqueScheduler.
3
5
  module ResqueCleaner
@@ -6,9 +8,6 @@ module ResqueCleaner
6
8
  def self.erb_path(filename)
7
9
  File.join(File.dirname(__FILE__), 'server', 'views', filename)
8
10
  end
9
- def self.public_path(filename)
10
- File.join(File.dirname(__FILE__), 'server', 'public', filename)
11
- end
12
11
 
13
12
  # Pagination helper for list page.
14
13
  class Paginate
@@ -97,6 +96,15 @@ module ResqueCleaner
97
96
  end
98
97
  html += "</select>"
99
98
  end
99
+
100
+ def show_job_args(args)
101
+ Array(args).map { |a| a.inspect }.join("\n")
102
+ end
103
+
104
+ def text_filter(id, name, value)
105
+ html = "<input id=\"#{id}\" type=\"text\" name=\"#{name}\" value=\"#{value}\">"
106
+ html += "</input>"
107
+ end
100
108
  end
101
109
 
102
110
  mime_type :json, 'application/json'
@@ -106,24 +114,28 @@ module ResqueCleaner
106
114
  load_cleaner_filter
107
115
 
108
116
  @jobs = cleaner.select
109
- @stats, @total = {}, {"total" => 0, "1h" => 0, "3h" => 0, "1d" => 0, "3d" => 0, "7d" => 0}
117
+ @stats = { :klass => {}, :exception => {} }
118
+ @total = Hash.new(0)
110
119
  @jobs.each do |job|
111
- klass = if job["payload"] && job["payload"]["class"]
112
- job["payload"]["class"]
113
- else
114
- "UNKNOWN"
115
- end
120
+ payload = job["payload"] || {}
121
+ klass = payload["class"] || 'UNKNOWN'
122
+ exception = job["exception"] || 'UNKNOWN'
116
123
  failed_at = Time.parse job["failed_at"]
117
-
118
- @stats[klass] ||= {"total" => 0, "1h" => 0, "3h" => 0, "1d" => 0, "3d" => 0, "7d" => 0}
119
- items = [@stats[klass],@total]
120
-
121
- items.each{|a| a["total"] += 1}
122
- items.each{|a| a["1h"] += 1} if failed_at >= hours_ago(1)
123
- items.each{|a| a["3h"] += 1} if failed_at >= hours_ago(3)
124
- items.each{|a| a["1d"] += 1} if failed_at >= hours_ago(24)
125
- items.each{|a| a["3d"] += 1} if failed_at >= hours_ago(24*3)
126
- items.each{|a| a["7d"] += 1} if failed_at >= hours_ago(24*7)
124
+ @stats[:klass][klass] ||= Hash.new(0)
125
+ @stats[:exception][exception] ||= Hash.new(0)
126
+
127
+ [
128
+ @stats[:klass][klass],
129
+ @stats[:exception][exception],
130
+ @total
131
+ ].each do |stat|
132
+ stat[:total] += 1
133
+ stat[:h1] += 1 if failed_at >= hours_ago(1)
134
+ stat[:h3] += 1 if failed_at >= hours_ago(3)
135
+ stat[:d1] += 1 if failed_at >= hours_ago(24)
136
+ stat[:d3] += 1 if failed_at >= hours_ago(24*3)
137
+ stat[:d7] += 1 if failed_at >= hours_ago(24*7)
138
+ end
127
139
  end
128
140
 
129
141
  erb File.read(ResqueCleaner::Server.erb_path('cleaner.erb'))
@@ -132,14 +144,13 @@ module ResqueCleaner
132
144
  get "/cleaner_list" do
133
145
  load_library
134
146
  load_cleaner_filter
147
+ build_urls
135
148
 
136
149
  block = filter_block
137
150
 
138
151
  @failed = cleaner.select(&block).reverse
139
152
 
140
- url = "cleaner_list?c=#{@klass}&ex=#{@exception}&f=#{@from}&t=#{@to}"
141
- @dump_url = "cleaner_dump?c=#{@klass}&ex=#{@exception}&f=#{@from}&t=#{@to}"
142
- @paginate = Paginate.new(@failed, url, params[:p].to_i)
153
+ @paginate = Paginate.new(@failed, @list_url, params[:p].to_i)
143
154
 
144
155
  @klasses = cleaner.stats_by_class.keys
145
156
  @exceptions = cleaner.stats_by_exception.keys
@@ -151,6 +162,7 @@ module ResqueCleaner
151
162
  post "/cleaner_exec" do
152
163
  load_library
153
164
  load_cleaner_filter
165
+ build_urls
154
166
 
155
167
  if params[:select_all_pages]!="1"
156
168
  @sha1 = {}
@@ -166,7 +178,6 @@ module ResqueCleaner
166
178
  when "retry" then cleaner.requeue(false,{},&block)
167
179
  end
168
180
 
169
- @url = "cleaner_list?c=#{@klass}&ex=#{@exception}&f=#{@from}&t=#{@to}"
170
181
  erb File.read(ResqueCleaner::Server.erb_path('cleaner_exec.erb'))
171
182
  end
172
183
 
@@ -185,10 +196,6 @@ module ResqueCleaner
185
196
  cleaner.clear_stale
186
197
  redirect url_path(:cleaner)
187
198
  end
188
-
189
- get /cleaner\/public\/([a-z]+\.[a-z]+)/ do
190
- send_file ResqueCleaner::Server.public_path(params[:captures].first)
191
- end
192
199
  end
193
200
 
194
201
  end
@@ -213,6 +220,20 @@ module ResqueCleaner
213
220
  @to = params[:t]=="" ? nil : params[:t]
214
221
  @klass = params[:c]=="" ? nil : params[:c]
215
222
  @exception = params[:ex]=="" ? nil : params[:ex]
223
+ @regex = params[:regex]=="" ? nil : params[:regex]
224
+ end
225
+
226
+ def build_urls
227
+ params = {
228
+ c: @klass,
229
+ ex: @exception,
230
+ f: @from,
231
+ t: @to,
232
+ regex: @regex
233
+ }.map {|key,value| "#{key}=#{URI.encode(value.to_s)}"}.join("&")
234
+
235
+ @list_url = "cleaner_list?#{params}"
236
+ @dump_url = "cleaner_dump?#{params}"
216
237
  end
217
238
 
218
239
  def filter_block
@@ -221,7 +242,8 @@ module ResqueCleaner
221
242
  (!@to || j.before?(hours_ago(@to))) &&
222
243
  (!@klass || j.klass?(@klass)) &&
223
244
  (!@exception || j.exception?(@exception)) &&
224
- (!@sha1 || @sha1[Digest::SHA1.hexdigest(j.to_json)])
245
+ (!@sha1 || @sha1[Digest::SHA1.hexdigest(j.to_json)]) &&
246
+ (!@regex || j.to_s =~ /#{@regex}/)
225
247
  }
226
248
  end
227
249
 
@@ -235,4 +257,3 @@ end
235
257
  Resque::Server.class_eval do
236
258
  include ResqueCleaner::Server
237
259
  end
238
-
@@ -7,7 +7,6 @@ module Resque
7
7
  # ResqueCleaner class provides useful functionalities to retry or clean
8
8
  # failed jobs. Let's clean up your failed list!
9
9
  class ResqueCleaner
10
- include Resque::Helpers
11
10
  # ResqueCleaner fetches all elements from Redis and checks them
12
11
  # by linear when filtering them. Since there is a performance concern,
13
12
  # ResqueCleaner handles only the latest x(default 1000) jobs.
@@ -91,6 +90,12 @@ module Resque
91
90
  end
92
91
  alias :failure_jobs :select
93
92
 
93
+ def select_by_regex(regex)
94
+ select do |job|
95
+ job.to_s =~ regex
96
+ end
97
+ end
98
+
94
99
  # Clears every jobs for which block evaluates to true.
95
100
  def clear(&block)
96
101
  cleared = 0
@@ -118,17 +123,21 @@ module Resque
118
123
  if !block_given? || block.call(job)
119
124
  index = @limiter.start_index + i - requeued
120
125
 
121
- if clear_after_requeue
122
- # remove job
123
- value = redis.lindex(:failed, index)
124
- redis.lrem(:failed, 1, value)
125
- else
126
- # mark retried
127
- job['retried_at'] = Time.now.strftime("%Y/%m/%d %H:%M:%S")
128
- redis.lset(:failed, @limiter.start_index+i, Resque.encode(job))
126
+ value = redis.lindex(:failed, index)
127
+ redis.multi do
128
+ Job.create(queue||job['queue'], job['payload']['class'], *job['payload']['args'])
129
+
130
+ if clear_after_requeue
131
+ # remove job
132
+ # TODO: should use ltrim. not sure why i used lrem here...
133
+ redis.lrem(:failed, 1, value)
134
+ else
135
+ # mark retried
136
+ job['retried_at'] = Time.now.strftime("%Y/%m/%d %H:%M:%S")
137
+ redis.lset(:failed, @limiter.start_index+i, Resque.encode(job))
138
+ end
129
139
  end
130
140
 
131
- Job.create(queue||job['queue'], job['payload']['class'], *job['payload']['args'])
132
141
  requeued += 1
133
142
  end
134
143
  end
data/test/dump.rdb ADDED
Binary file
data/test/redis-test.conf CHANGED
@@ -112,4 +112,4 @@ databases 16
112
112
  # Glue small output buffers together in order to send small replies in a
113
113
  # single TCP packet. Uses a bit more CPU but most of the times it is a win
114
114
  # in terms of number of queries per second. Use 'yes' if unsure.
115
- glueoutputbuf yes
115
+ #glueoutputbuf yes
@@ -1,7 +1,7 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
  require 'time'
3
- context "ResqueCleaner" do
4
- setup do
3
+ describe "ResqueCleaner" do
4
+ before do
5
5
  Resque.redis.flushall
6
6
 
7
7
  @worker = Resque::Worker.new(:jobs,:jobs2)
@@ -28,41 +28,53 @@ context "ResqueCleaner" do
28
28
  @cleaner.print_message = false
29
29
  end
30
30
 
31
- test "#select returns failure jobs" do
31
+ it "#select_by_regex returns only Jason jobs" do
32
+ ret = @cleaner.select_by_regex(/Jason/)
33
+ assert_equal 13, ret.size
34
+ end
35
+
36
+ it "#select_by_regex returns an empty array if passed a non-regex" do
37
+ ['string', nil, 13, Class.new].each do |non_regex|
38
+ ret = @cleaner.select_by_regex(nil)
39
+ assert_equal 0, ret.size
40
+ end
41
+ end
42
+
43
+ it "#select returns failure jobs" do
32
44
  ret = @cleaner.select
33
45
  assert_equal 42, ret.size
34
46
  end
35
47
 
36
- test "#select works with a limit" do
48
+ it "#select works with a limit" do
37
49
  @cleaner.limiter.maximum = 10
38
50
  ret = @cleaner.select
39
51
 
40
52
  # only maximum number
41
53
  assert_equal 10, ret.size
42
54
 
43
- # latest one
55
+ # lait one
44
56
  assert_equal Time.parse(ret[0]['failed_at']), Time.parse('2010-08-13')
45
57
  end
46
58
 
47
- test "#select with a block returns failure jobs which the block evaluates true" do
59
+ it "#select with a block returns failure jobs which the block evaluates true" do
48
60
  ret = @cleaner.select {|job| job["payload"]["args"][0]=="Jason"}
49
61
  assert_equal 13, ret.size
50
62
  end
51
63
 
52
- test "#clear deletes failure jobs" do
64
+ it "#clear deletes failure jobs" do
53
65
  cleared = @cleaner.clear
54
66
  assert_equal 42, cleared
55
67
  assert_equal 0, @cleaner.select.size
56
68
  end
57
69
 
58
- test "#clear with a block deletes failure jobs which the block evaluates true" do
70
+ it "#clear with a block deletes failure jobs which the block evaluates true" do
59
71
  cleared = @cleaner.clear{|job| job["payload"]["args"][0]=="Jason"}
60
72
  assert_equal 13, cleared
61
73
  assert_equal 42-13, @cleaner.select.size
62
74
  assert_equal 0, @cleaner.select{|job| job["payload"]["args"][0]=="Jason"}.size
63
75
  end
64
76
 
65
- test "#requeue retries failure jobs" do
77
+ it "#requeue retries failure jobs" do
66
78
  assert_equal 0, queue_size(:jobs,:jobs2)
67
79
  requeued = @cleaner.requeue
68
80
  assert_equal 42, requeued
@@ -70,13 +82,13 @@ context "ResqueCleaner" do
70
82
  assert_equal 42, queue_size(:jobs,:jobs2)
71
83
  end
72
84
 
73
- test "#requeue with a block retries failure jobs which the block evaluates true" do
85
+ it "#requeue with a block retries failure jobs which the block evaluates true" do
74
86
  requeued = @cleaner.requeue{|job| job["payload"]["args"][0]=="Jason"}
75
87
  assert_equal 13, requeued
76
88
  assert_equal 13, queue_size(:jobs,:jobs2)
77
89
  end
78
90
 
79
- test "#requeue with clear option requeues and deletes failure jobs" do
91
+ it "#requeue with clear option requeues and deletes failure jobs" do
80
92
  assert_equal 0, queue_size(:jobs,:jobs2)
81
93
  requeued = @cleaner.requeue(true)
82
94
  assert_equal 42, requeued
@@ -84,7 +96,7 @@ context "ResqueCleaner" do
84
96
  assert_equal 0, @cleaner.select.size
85
97
  end
86
98
 
87
- test "#requeue with :queue option requeues the jobs to the queue" do
99
+ it "#requeue with :queue option requeues the jobs to the queue" do
88
100
  assert_equal 0, queue_size(:jobs,:jobs2,:retry)
89
101
  requeued = @cleaner.requeue false, :queue => :retry
90
102
  assert_equal 42, requeued
@@ -93,14 +105,14 @@ context "ResqueCleaner" do
93
105
  assert_equal 42, queue_size(:retry)
94
106
  end
95
107
 
96
- test "#clear_stale deletes failure jobs which is queued before the last x enqueued" do
108
+ it "#clear_stale deletes failure jobs which is queued before the last x enqueued" do
97
109
  @cleaner.limiter.maximum = 10
98
110
  @cleaner.clear_stale
99
111
  assert_equal 10, @cleaner.failure.count
100
112
  assert_equal Time.parse(@cleaner.failure_jobs[0]['failed_at']), Time.parse('2010-08-13')
101
113
  end
102
114
 
103
- test "FailedJobEx module extends job and provides some useful methods" do
115
+ it "FailedJobEx module extends job and provides some useful methods" do
104
116
  # before 2009-04-01
105
117
  ret = @cleaner.select {|j| j.before?('2009-04-01')}
106
118
  assert_equal 6, ret.size
@@ -135,7 +147,7 @@ context "ResqueCleaner" do
135
147
  assert_equal 1, ret.size
136
148
  end
137
149
 
138
- test "#stats_by_date returns stats grouped by date" do
150
+ it "#stats_by_date returns stats grouped by date" do
139
151
  ret = @cleaner.stats_by_date
140
152
  assert_equal 6, ret['2009/03/13']
141
153
  assert_equal 14, ret['2009/11/13']
@@ -147,25 +159,25 @@ context "ResqueCleaner" do
147
159
  assert_equal 11, ret['2010/08/13']
148
160
  end
149
161
 
150
- test "#stats_by_class returns stats grouped by class" do
162
+ it "#stats_by_class returns stats grouped by class" do
151
163
  ret = @cleaner.stats_by_class
152
164
  assert_equal 35, ret['BadJob']
153
165
  assert_equal 7, ret['BadJobWithSyntaxError']
154
166
  end
155
167
 
156
- test "#stats_by_class works with broken log" do
168
+ it "#stats_by_class works with broken log" do
157
169
  add_empty_payload_failure
158
170
  ret = @cleaner.stats_by_class
159
171
  assert_equal 1, ret['UNKNOWN']
160
172
  end
161
173
 
162
- test "#stats_by_exception returns stats grouped by exception" do
174
+ it "#stats_by_exception returns stats grouped by exception" do
163
175
  ret = @cleaner.stats_by_exception
164
176
  assert_equal 35, ret['RuntimeError']
165
177
  assert_equal 7, ret['SyntaxError']
166
178
  end
167
179
 
168
- test "#lock ensures that a new failure job doesn't affect in a limit mode" do
180
+ it "#lock ensures that a new failure job doesn't affect in a limit mode" do
169
181
  @cleaner.limiter.maximum = 23
170
182
  @cleaner.limiter.lock do
171
183
  first = @cleaner.select[0]
@@ -180,9 +192,9 @@ context "ResqueCleaner" do
180
192
  assert_equal "Jack", first["payload"]["args"][0]
181
193
  end
182
194
 
183
- test "allows you to configure limiter" do
195
+ it "allows you to configure limiter" do
184
196
  c = Resque::Plugins::ResqueCleaner.new
185
- assert_not_equal c.limiter.maximum, 10_000
197
+ refute_equal c.limiter.maximum, 10_000
186
198
 
187
199
  module Resque::Plugins
188
200
  ResqueCleaner::Limiter.default_maximum = 10_000
@@ -1,15 +1,23 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/test_helper')
2
2
 
3
- # Pull in the server test_helper from resque
4
- require 'resque/server/test_helper.rb'
5
3
  require 'digest/sha1'
6
4
  require 'json'
5
+ require 'rack/test'
6
+
7
+ class Minitest::Spec
8
+ include Rack::Test::Methods
9
+ def app
10
+ Resque::Server.new
11
+ end
12
+ end
7
13
 
8
14
  def setup_some_failed_jobs
9
15
  Resque.redis.flushall
10
16
 
11
17
  @worker = Resque::Worker.new(:jobs,:jobs2)
12
18
 
19
+ create_and_process_jobs :jobs, @worker, 1, Time.now, BadJobWithSyntaxError, "great_args"
20
+
13
21
  10.times {|i|
14
22
  create_and_process_jobs :jobs, @worker, 1, Time.now, BadJob, "test_#{i}"
15
23
  }
@@ -18,31 +26,39 @@ def setup_some_failed_jobs
18
26
  @cleaner.print_message = false
19
27
  end
20
28
 
21
- context "resque-web" do
22
- setup do
29
+ describe "resque-web" do
30
+ before do
23
31
  setup_some_failed_jobs
24
32
  end
25
33
 
26
- test "#cleaner should respond with success" do
27
- get "/cleaner_list"
28
- assert last_response.ok?, last_response.errors
34
+ it "#cleaner should respond with success" do
35
+ get "/cleaner"
36
+ assert last_response.body.include?('BadJob')
37
+ assert last_response.body =~ /\bException\b/
29
38
  end
30
39
 
31
- test "#cleaner_list should respond with success" do
40
+ it "#cleaner_list should respond with success" do
32
41
  get "/cleaner_list"
33
42
  assert last_response.ok?, last_response.errors
34
43
  end
35
44
 
36
- test '#cleaner_list shows the failed jobs' do
45
+ it '#cleaner_list shows the failed jobs' do
37
46
  get "/cleaner_list"
38
47
  assert last_response.body.include?('BadJob')
39
48
  end
40
49
 
41
- test '#cleaner_exec clears job' do
50
+ it "#cleaner_list shows the failed jobs when we use a select_by_regex" do
51
+ get "/cleaner_list", :regex => "BadJob*"
52
+ assert last_response.body.include?('"BadJobWithSyntaxError"')
53
+ assert last_response.body.include?('"BadJob"')
54
+ end
55
+
56
+
57
+ it '#cleaner_exec clears job' do
42
58
  post "/cleaner_exec", :action => "clear", :sha1 => Digest::SHA1.hexdigest(@cleaner.select[0].to_json)
43
- assert_equal 9, @cleaner.select.size
59
+ assert_equal 10, @cleaner.select.size
44
60
  end
45
- test "#cleaner_dump should respond with success" do
61
+ it "#cleaner_dump should respond with success" do
46
62
  get "/cleaner_dump"
47
63
  assert last_response.ok?, last_response.errors
48
64
  end
data/test/test_helper.rb CHANGED
@@ -4,8 +4,10 @@
4
4
  dir = File.dirname(File.expand_path(__FILE__))
5
5
  $LOAD_PATH.unshift dir + '/../lib'
6
6
  $TESTING = true
7
- require 'test/unit'
8
7
  require 'rubygems'
8
+ require 'minitest'
9
+ require 'minitest/spec'
10
+ require 'minitest/autorun'
9
11
  require 'resque'
10
12
  require 'timecop'
11
13
 
@@ -16,6 +18,8 @@ end
16
18
  require 'resque'
17
19
  require 'resque_cleaner'
18
20
 
21
+ $TEST_PID = Process.pid
22
+
19
23
  #
20
24
  # make sure we can run redis
21
25
  #
@@ -31,48 +35,22 @@ end
31
35
  # start our own redis when the tests start,
32
36
  # kill it when they end
33
37
  #
34
-
35
- at_exit do
36
- next if $!
37
-
38
- if defined?(MiniTest)
39
- exit_code = MiniTest::Unit.new.run(ARGV)
40
- else
41
- exit_code = Test::Unit::AutoRunner.run
38
+ MiniTest.after_run {
39
+ if Process.pid == $TEST_PID
40
+ processes = `ps -A -o pid,command | grep [r]edis-test`.split($/)
41
+ pids = processes.map { |process| process.split(" ")[0] }
42
+ puts "Killing test redis server..."
43
+ pids.each { |pid| Process.kill("TERM", pid.to_i) }
44
+ dump = "test/dump.rdb"
45
+ File.delete(dump) if File.exist?(dump)
42
46
  end
43
-
44
- pid = `ps -A -o pid,command | grep [r]edis-test`.split(" ")[0]
45
- puts "Killing test redis server..."
46
- `rm -f #{dir}/dump.rdb`
47
- Process.kill("KILL", pid.to_i)
48
- exit exit_code
49
- end
47
+ }
50
48
 
51
49
  puts "Starting redis for testing at localhost:9736..."
52
50
  `redis-server #{dir}/redis-test.conf`
53
51
  Resque.redis = 'localhost:9736'
54
52
 
55
53
 
56
- ##
57
- # test/spec/mini 3
58
- # http://gist.github.com/25455
59
- # chris@ozmm.org
60
- #
61
- def context(*args, &block)
62
- return super unless (name = args.first) && block
63
- require 'test/unit'
64
- klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
65
- def self.test(name, &block)
66
- define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
67
- end
68
- def self.xtest(*args) end
69
- def self.setup(&block) define_method(:setup, &block) end
70
- def self.teardown(&block) define_method(:teardown, &block) end
71
- end
72
- (class << klass; self end).send(:define_method, :name) { name.gsub(/\W/,'_') }
73
- klass.class_eval &block
74
- end
75
-
76
54
  ##
77
55
  # Helper to perform job classes
78
56
  #
metadata CHANGED
@@ -1,32 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-cleaner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.10
5
- prerelease:
4
+ version: 0.4.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Tatsuya Ono
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-10-15 00:00:00.000000000 Z
11
+ date: 2018-01-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: resque
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - ! '>='
20
18
  - !ruby/object:Gem::Version
21
- version: '1.0'
19
+ version: '0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
26
30
  requirements:
27
31
  - - ~>
28
32
  - !ruby/object:Gem::Version
29
- version: '1.0'
33
+ version: '5.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '5.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack-test
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.6.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.6.0
30
55
  description: ! ' resque-cleaner maintains the cleanliness of failed jobs on Resque.
31
56
 
32
57
  '
@@ -35,50 +60,52 @@ executables: []
35
60
  extensions: []
36
61
  extra_rdoc_files:
37
62
  - LICENSE
38
- - README.markdown
63
+ - README.md
39
64
  - CHANGELOG.md
40
65
  files:
41
- - README.markdown
66
+ - README.md
42
67
  - CHANGELOG.md
43
68
  - Rakefile
44
69
  - LICENSE
45
70
  - lib/resque-cleaner.rb
46
- - lib/resque_cleaner/server/public/cleaner.css
71
+ - lib/resque_cleaner/server/views/_cleaner_styles.erb
47
72
  - lib/resque_cleaner/server/views/_limiter.erb
48
73
  - lib/resque_cleaner/server/views/_paginate.erb
74
+ - lib/resque_cleaner/server/views/_stats.erb
49
75
  - lib/resque_cleaner/server/views/cleaner.erb
50
76
  - lib/resque_cleaner/server/views/cleaner_exec.erb
51
77
  - lib/resque_cleaner/server/views/cleaner_list.erb
52
78
  - lib/resque_cleaner/server.rb
53
79
  - lib/resque_cleaner.rb
80
+ - test/dump.rdb
54
81
  - test/redis-test.conf
55
82
  - test/resque_cleaner_test.rb
56
83
  - test/resque_web_test.rb
57
84
  - test/test_helper.rb
58
- homepage: http://github.com/ono/resque-cleaner
59
- licenses: []
85
+ homepage: https://github.com/ono/resque-cleaner
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
60
89
  post_install_message:
61
90
  rdoc_options:
62
91
  - --charset=UTF-8
63
92
  require_paths:
64
93
  - lib
65
94
  required_ruby_version: !ruby/object:Gem::Requirement
66
- none: false
67
95
  requirements:
68
96
  - - ! '>='
69
97
  - !ruby/object:Gem::Version
70
- version: '0'
98
+ version: 1.9.3
71
99
  required_rubygems_version: !ruby/object:Gem::Requirement
72
- none: false
73
100
  requirements:
74
101
  - - ! '>='
75
102
  - !ruby/object:Gem::Version
76
103
  version: '0'
77
104
  requirements: []
78
105
  rubyforge_project:
79
- rubygems_version: 1.8.23
106
+ rubygems_version: 2.1.11
80
107
  signing_key:
81
- specification_version: 3
108
+ specification_version: 4
82
109
  summary: Resque plugin cleaning up failed jobs.
83
110
  test_files: []
84
111
  has_rdoc:
@@ -1,64 +0,0 @@
1
-
2
- #main .cleaner .title h1 { float: left }
3
-
4
- #main .cleaner .sub_header {color: #888; font-size: 80%; font-weight: bold}
5
-
6
- #main .cleaner .control_panel {
7
- margin: 5px 0 10px; padding: 5px; background: #eee; display: inline-block;
8
- -webkit-border-radius:5px; border:1px solid #ccc;
9
- }
10
-
11
- #main .cleaner #exec { color: black; }
12
- #main .cleaner #exec select { margin-right: 20px }
13
- #main .cleaner #exec a { margin-right: 5px}
14
- #main .cleaner #exec a.disabled { color: #aaa}
15
-
16
- #main .cleaner table.class_list { width: auto }
17
- #main .cleaner td.number { text-align: right }
18
- #main .cleaner tr.total { border-top: 3px double #ccc}
19
-
20
- #main .cleaner form { float: none; margin: 0}
21
-
22
- #main .cleaner .warning { margin: 30px 0; padding: 10px; background: #fdd; display: inline-block; }
23
-
24
- #main .clearfix:after {
25
- content: ".";
26
- display: block;
27
- height: 0;
28
- clear: both;
29
- visibility: hidden;
30
- }
31
- #main .cleaner ul.failed {
32
- margin-bottom: 10px
33
- }
34
-
35
- #main .cleaner .list_info{
36
- color: #999; text-align: center;
37
- }
38
- #main .cleaner .list_info a{
39
- color: #666
40
- }
41
- #main .cleaner .list_info .list_summary{
42
- vertical-align: baseline;
43
- display: inline-block;
44
- margin: 0; padding:0;
45
- }
46
- #main .cleaner ul.pagination {
47
- display: inline-block;
48
- vertical-align: baseline;
49
- margin:0; padding:0;
50
- }
51
- #main .cleaner ul.pagination li {
52
- list-style:none; float: left; padding: 0 3px;
53
- }
54
- #main .cleaner ul.pagination li.current {
55
- color: #333; font-weight: bold;
56
- }
57
- #main .cleaner ul.pagination li.summary{
58
- padding-right: 10px
59
- }
60
- #main .cleaner div.dump{
61
- float: right
62
- }
63
-
64
-