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

Job duration #109

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
20 changes: 16 additions & 4 deletions lib/resque/plugins/status.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ def initialize(uuid, options = {})
# If an error occurs within the job's work, it will set the status as failed and
# re-raise the error.
def safe_perform!
set_status({'status' => STATUS_WORKING})
set_status({
'status' => STATUS_WORKING,
'started_at' => Time.now.to_i
})
perform
if status && status.failed?
on_failure(status.message) if respond_to?(:on_failure)
Expand Down Expand Up @@ -219,26 +222,35 @@ def at(num, total, *messages)
# <tt>Resque::Plugins::Status::Hash.kill()</tt>
def tick(*messages)
kill! if should_kill?
set_status({'status' => STATUS_WORKING}, *messages)

status_options = {'status' => STATUS_WORKING}
status_options.merge!('started_at' => Time.now.to_i) unless status.working?

set_status(status_options, *messages)
end

# set the status to 'failed' passing along any additional messages
def failed(*messages)
set_status({'status' => STATUS_FAILED}, *messages)
set_status({
'status' => STATUS_FAILED,
'finished_at' => Time.now.to_i,
}, *messages)
end

# set the status to 'completed' passing along any addional messages
def completed(*messages)
set_status({
'status' => STATUS_COMPLETED,
'finished_at' => Time.now.to_i,
'message' => "Completed at #{Time.now}"
}, *messages)
}, *messages)
end

# kill the current job, setting the status to 'killed' and raising <tt>Killed</tt>
def kill!
set_status({
'status' => STATUS_KILLED,
'finished_at' => Time.now.to_i,
'message' => "Killed at #{Time.now}"
})
raise Killed
Expand Down
28 changes: 28 additions & 0 deletions lib/resque/plugins/status/hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ class << self
hash_accessor :num
hash_accessor :total

#adds start- & end-time for processing
hash_accessor :started_at
hash_accessor :finished_at

# Create a new Resque::Plugins::Status::Hash object. If multiple arguments are passed
# it is assumed the first argument is the UUID and the rest are status objects.
# All arguments are subsequentily merged in order. Strings are assumed to
Expand Down Expand Up @@ -242,6 +246,30 @@ def time
time? ? Time.at(self['time']) : nil
end

# Returns the duration the job took to be performed or to current time
# when it's not done yet
# format can be given to format time
def duration(format = "%H:%M:%S")
duration = nil
if completed? or failed? or killed?
duration = self['finished_at'] - self['started_at']
elsif working?
duration = Time.now.to_i - self['started_at']
end

duration.nil? ? nil : Time.at(duration).utc.strftime(format)
end

# Returns the time when the perform was called
def started_at
started_at? ? Time.at(self['started_at']) : nil
end

# Returns the time when the processing was completed / failed
def finished_at
finished_at? ? Time.at(self['finished_at']) : nil
end

Resque::Plugins::Status::STATUSES.each do |status|
define_method("#{status}?") do
self['status'] === status
Expand Down
3 changes: 2 additions & 1 deletion lib/resque/server/views/status.erb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
.attr('class', '')
.addClass('status-progress-bar status-' + json.status);
}

if (json.time) {
$status.find('.status-time').text(new Date(json.time * 1000).toString())
}
Expand All @@ -76,7 +77,7 @@
};

function printValue(key, value) {
if (/(^|_)time$/.test(key) && typeof value == 'number') {
if (/(^|_)(time|started_at|finished_at)$/.test(key) && typeof value == 'number') {
var time = new Date();
time.setTime(value * 1000);
return time.toUTCString();
Expand Down
2 changes: 2 additions & 0 deletions lib/resque/server/views/statuses.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<th>Last Updated</th>
<th class="progress">% Complete</th>
<th>Message</th>
<th>Duration</th>
<th>Kill</th>
</tr>
<% unless @statuses.empty? %>
Expand All @@ -35,6 +36,7 @@
<div class="progress-pct"><%= status.pct_complete ? "#{status.pct_complete}%" : '' %></div>
</td>
<td><%= status.message %></td>
<td><%= status.duration %></td>
<td><% if status.killable? %><a href="<%= u(:statuses) %>/<%= status.uuid %>/kill" class="kill">Kill</a><% end %></td>
</tr>
<% end %>
Expand Down