Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add redis queries improvements and add clear_one route for huge failed list #43

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 33 additions & 13 deletions lib/resque_cleaner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,26 @@ def stats_by_exception(&block)
stats
end

# Stats by exception & class & date.
def get_all_stats(&block)
jobs, stats = select(&block), { exception: {}, klass: {}, date: {} }
jobs.each do |job|
date = job["failed_at"][0,10]
stats[:date][date] ||= 0
stats[:date][date] += 1

exception = job["exception"]
stats[:exception][exception] ||= 0
stats[:exception][exception] += 1

klass = job["payload"] && job["payload"]["class"] ? job["payload"]["class"] : "UNKNOWN"
stats[:klass][klass] ||= 0
stats[:klass][klass] += 1
end

stats
end

# Print stats
def print_stats(stats)
log too_many_message if @limiter.on?
Expand All @@ -85,8 +105,7 @@ def print_stats(stats)

# Returns every jobs for which block evaluates to true.
def select(&block)
jobs = @limiter.jobs
block_given? ? @limiter.jobs.select(&block) : jobs
block_given? ? @limiter.jobs.select(&block) : @limiter.jobs
end
alias :failure_jobs :select

Expand All @@ -104,7 +123,7 @@ def clear(&block)
if !block_given? || block.call(job)
index = @limiter.start_index + i - cleared
# fetches again since you can't ensure that it is always true:
# a == endode(decode(a))
# a == encode(decode(a))
value = redis.lindex(:failed, index)
redis.lrem(:failed, 1, value)
cleared += 1
Expand Down Expand Up @@ -153,7 +172,7 @@ def clear_stale
c
end

# Exntends job(Hash instance) with some helper methods.
# Extends job(Hash instance) with some helper methods.
module FailedJobEx
# Returns true if the job has been already retried. Otherwise returns
# false.
Expand Down Expand Up @@ -213,7 +232,7 @@ def default_maximum=(v)
end
end

attr_accessor :maximum
attr_accessor :maximum, :start_offset, :count_failed
def initialize(cleaner)
@cleaner = cleaner
@maximum = @@default_maximum
Expand All @@ -240,14 +259,16 @@ def count
def jobs
if @locked
@jobs
elsif start_offset && count_failed
all(start_offset, count_failed)
else
all( - count, count)
all(-count, count)
end
end

# Wraps Resque's all and returns always array.
def all(index=0,count=1)
jobs = @cleaner.failure.all( index, count)
jobs = @cleaner.failure.all(index, count)
jobs = [] unless jobs
jobs = [jobs] unless jobs.is_a?(Array)
jobs.each{|j| j.extend FailedJobEx}
Expand All @@ -259,7 +280,7 @@ def start_index
if @locked
@start_index
else
on? ? @cleaner.failure.count-@maximum : 0
on? ? @cleaner.failure.count - @maximum : 0
end
end

Expand All @@ -270,12 +291,12 @@ def lock

unless @locked
total_count = @cleaner.failure.count
if total_count>@maximum
@start_index = total_count-@maximum
@jobs = all( @start_index, @maximum)
if total_count > @maximum
@start_index = total_count - @maximum
@jobs = all(@start_index, @maximum)
else
@start_index = 0
@jobs = all( 0, total_count)
@jobs = all(0, total_count)
end
end

Expand Down Expand Up @@ -304,4 +325,3 @@ def too_many_message
end

require 'resque_cleaner/server'

47 changes: 37 additions & 10 deletions lib/resque_cleaner/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def initialize(jobs, url, page=1, page_size=20)
@jobs = jobs
@url = url
@page = (!page || page < 1) ? 1 : page
@page_size = 20
@page_size = page_size
end

def first_index
Expand All @@ -28,11 +28,11 @@ def first_index

def last_index
last = first_index + @page_size - 1
last > @jobs.size-1 ? @jobs.size-1 : last
last > @jobs.size - 1 ? @jobs.size - 1 : last
end

def paginated_jobs
@jobs[first_index,@page_size]
@jobs[first_index, @page_size]
end

def first_page?
Expand All @@ -58,7 +58,7 @@ def total_size
end

def max_page
((total_size-1) / @page_size) + 1
((total_size - 1) / @page_size) + 1
end
end

Expand Down Expand Up @@ -151,17 +151,36 @@ def text_filter(id, name, value)

block = filter_block

@failed = cleaner.select(&block).reverse
selected_jobs = cleaner.select(&block)
@failed = selected_jobs.reverse
@count = selected_jobs.size

@paginate = Paginate.new(@failed, @list_url, params[:p].to_i)

@klasses = cleaner.stats_by_class.keys
@exceptions = cleaner.stats_by_exception.keys
@count = cleaner.select(&block).size
all_stats = cleaner.get_all_stats
@klasses = all_stats[:klass].keys
@exceptions = all_stats[:exception].keys

erb File.read(ResqueCleaner::Server.erb_path('cleaner_list.erb'))
end

get "/cleaner_one" do
load_library
load_cleaner_filter
set_failed_list_indexes

@total = cleaner.failure.count

block = filter_block

selected_jobs = cleaner.select(&block)
@failed = selected_jobs.reverse

@count = selected_jobs.size

erb File.read(ResqueCleaner::Server.erb_path('cleaner_one.erb'))
end

post "/cleaner_exec" do
load_library
load_cleaner_filter
Expand Down Expand Up @@ -244,7 +263,7 @@ def build_urls
end

def filter_block
block = lambda{|j|
lambda{|j|
(!@from || j.after?(hours_ago(@from))) &&
(!@to || j.before?(hours_ago(@to))) &&
(!@klass || j.klass?(@klass)) &&
Expand All @@ -254,6 +273,15 @@ def filter_block
}
end

def set_failed_list_indexes
failed_start_index = params[:fsi].nil? ? nil : params[:fsi].to_i
count_failed = params[:cf].nil? ? nil : params[:cf].to_i
return unless failed_start_index && count_failed

cleaner.limiter.start_offset = failed_start_index
cleaner.limiter.count_failed = count_failed
end

def hours_ago(h)
Time.now - h.to_i*60*60
end
Expand All @@ -264,4 +292,3 @@ def hours_ago(h)
Resque::Server.class_eval do
include ResqueCleaner::Server
end

10 changes: 10 additions & 0 deletions lib/resque_cleaner/server/public/cleaner.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,15 @@
#main .cleaner div.dump{
float: right
}
#main .cleaner .start-indexes {
float: right;
padding: 7px;
background-color: #eee;
border-radius: 5px;
margin: 5px;
border: 1px solid #ccc;
text-decoration: none;
}



28 changes: 14 additions & 14 deletions lib/resque_cleaner/server/views/_paginate.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,53 @@

<ul class="pagination">
<li class="summary">
<%= @paginate.first_index%> - <%= @paginate.last_index%> / <%= @paginate.total_size%>
<%= @paginate.first_index %> - <%= @paginate.last_index %> / <%= @paginate.total_size %>
</li>
<% if @paginate.max_page>1 %>
<% if @paginate.max_page >1 %>
<% if @paginate.first_page? %>
<li class="prev off">&lt;&lt;newer</li>
<% else %>
<li class="prev"><a href="<%= @paginate.page_url(:prev)%>">&lt;&lt;newer</a></li>
<% end %>

<% 1.upto(6<@paginate.max_page ? 6 : @paginate.max_page) do |pg| %>
<% 1.upto(6 < @paginate.max_page ? 6 : @paginate.max_page) do |pg| %>
<% if @paginate.page==pg %>
<li class="current"><%=pg%></li>
<li class="current"><%= pg %></li>
<% else %>
<li><a href="<%= @paginate.page_url(pg)%>"><%=pg%></a></li>
<li><a href="<%= @paginate.page_url(pg) %>"><%= pg %></a></li>
<% end %>
<% end %>

<% if @paginate.max_page > 6 %>
<% if @paginate.max_page!=@paginate.page %>
<% if @paginate.max_page != @paginate.page %>
<% if @paginate.page>7 %>
<li class="off">...</li>
<% end %>
<% if @paginate.page>6 %>
<li class="current"><%[email protected]%></li>
<% if @paginate.page > 6 %>
<li class="current"><%= @paginate.page %></li>
<% end %>
<% end %>
<% if @paginate.max_page>7 && @paginate.page+1!=@paginate.max_page %>
<% if @paginate.max_page > 7 && @paginate.page + 1 != @paginate.max_page %>
<li class="off">...</li>
<% end %>

<% if @paginate.max_page==@paginate.page %>
<li class="current"><%[email protected]_page%></li>
<% if @paginate.max_page == @paginate.page %>
<li class="current"><%= @paginate.max_page %></li>
<% else %>
<li><a href="<%= @paginate.page_url(@paginate.max_page)%>"><%[email protected]_page%></a></li>
<li><a href="<%= @paginate.page_url(@paginate.max_page)%>"><%= @paginate.max_page %></a></li>
<% end %>
<% end %>

<% if @paginate.last_page? %>
<li class="next off">older&gt;&gt;</li>
<% else %>
<li class="next"><a href="<%= @paginate.page_url(:next)%>">older&gt;&gt;</a></li>
<li class="next"><a href="<%= @paginate.page_url(:next) %>">older&gt;&gt;</a></li>
<% end %>
<% end %>

</ul>
<div class="dump">
<a href="<%= @dump_url%>" target="_blank">Dump</a>
<a href="<%= @dump_url %>" target="_blank">Dump</a>
</div>
</div>

5 changes: 3 additions & 2 deletions lib/resque_cleaner/server/views/_stats.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
<th>In last 3 days</th>
<th>In last 7 days</th>
</tr>
<% @stats[type.to_sym].each do |field,count| %>
<% @stats[type.to_sym].each do |field, count| %>
<tr>
<% filter = "#{q}=#{URI.encode(field)}" %>
<td><%= field %></td>
<% label = type == 'klass' ? "<a href='cleaner_one?c=#{field}'&fsi=10&cf=50>#{field}</a>" : field %>
<td><%= label %></td>
<td class="number">
<a href="cleaner_list?<%=filter%>"><%= count[:total] %></a>
</td>
Expand Down
2 changes: 1 addition & 1 deletion lib/resque_cleaner/server/views/cleaner_exec.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<div class="cleaner">
<p class="message">Processed <%= @count %> jobs.</p>
<p class="back_to_list">
<a href="<%=@list_url%>">Back to List</a>
<a href="<%= @list_url %>">Back to List</a>
</p>
</div>
7 changes: 3 additions & 4 deletions lib/resque_cleaner/server/views/cleaner_list.erb
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,14 @@
</div>
<% end %>

<% start = 0 %>
<% failed = @paginate.paginated_jobs%>
<% index = 0 %>
<% date_format = "%Y/%m/%d %T %z" %>

<% if @paginate.max_page > 0 %>
<%= erb File.read(ResqueCleaner::Server.erb_path("_paginate.erb")) %>
<ul class='failed'>
<%for job in failed%>
<% failed.each do |job| %>
<% index += 1 %>
<li>
<dl>
Expand Down Expand Up @@ -108,7 +107,7 @@
<div class='r'>
</div>
</li>
<%end%>
<% end %>
</ul>
<%= erb File.read(ResqueCleaner::Server.erb_path("_paginate.erb")) %>
<% else %>
Expand Down Expand Up @@ -174,6 +173,6 @@
$('#exec a').removeClass('disabled');
$('.failed input').removeAttr('disabled');
}
};
}

</script>
Loading