diff --git a/README.md b/README.md index c42f760..2da8c80 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,8 @@ Sidekiq::Status::at job_id #=> 5 Sidekiq::Status::total job_id #=> 100 Sidekiq::Status::message job_id #=> "Almost done" Sidekiq::Status::pct_complete job_id #=> 5 +Sidekiq::Status::working_at job_id #=> 2718 +Sidekiq::Status::update_time job_id #=> 2819 ``` ### Unscheduling diff --git a/lib/sidekiq-status.rb b/lib/sidekiq-status.rb index 9ef3b8b..ca1c9ad 100644 --- a/lib/sidekiq-status.rb +++ b/lib/sidekiq-status.rb @@ -63,6 +63,21 @@ def pct_complete(job_id) get(job_id, :pct_complete).to_i end + def working_at(job_id) + (get(job_id, :working_at) || Time.now).to_i + end + + def update_time(job_id) + (get(job_id, :update_time) || Time.now).to_i + end + + def eta(job_id) + at = at(job_id) + return nil if at.zero? + + (Time.now.to_i - working_at(job_id)).to_f / at * (total(job_id) - at) + end + def message(job_id) get(job_id, :message) end diff --git a/lib/sidekiq-status/web.rb b/lib/sidekiq-status/web.rb index da466a2..c51bbad 100644 --- a/lib/sidekiq-status/web.rb +++ b/lib/sidekiq-status/web.rb @@ -8,7 +8,7 @@ module Web DEFAULT_PER_PAGE_OPTS = [25, 50, 100].freeze DEFAULT_PER_PAGE = 25 - COMMON_STATUS_HASH_KEYS = %w(update_time jid status worker args label pct_complete total at message) + COMMON_STATUS_HASH_KEYS = %w(update_time jid status worker args label pct_complete total at message working_at elapsed eta) class << self def per_page_opts= arr @@ -48,6 +48,8 @@ def sidekiq_status_template(name) def add_details_to_status(status) status['label'] = status_label(status['status']) status["pct_complete"] ||= pct_complete(status) + status["elapsed"] ||= elapsed(status).to_s + status["eta"] ||= eta(status).to_s status["custom"] = process_custom_data(status) return status end @@ -61,6 +63,19 @@ def pct_complete(status) Sidekiq::Status::pct_complete(status['jid']) || 0 end + def elapsed(status) + case status['status'] + when 'complete' + Sidekiq::Status.update_time(status['jid']) - Sidekiq::Status.working_at(status['jid']) + when 'working', 'retrying' + Time.now.to_i - Sidekiq::Status.working_at(status['jid']) + end + end + + def eta(status) + Sidekiq::Status.eta(status['jid']) if status['status'] == 'working' + end + def status_label(status) case status when 'complete' @@ -122,6 +137,8 @@ def has_sort_by?(value) {id: "status", name: "Status", class: nil, url: nil}, {id: "update_time", name: "Last Updated", class: nil, url: nil}, {id: "pct_complete", name: "Progress", class: nil, url: nil}, + {id: "elapsed", name: "Time Elapsed", class: nil, url: nil}, + {id: "eta", name: "ETA", class: nil, url: nil}, ] @headers.each do |h| diff --git a/lib/sidekiq-status/worker.rb b/lib/sidekiq-status/worker.rb index 8011e9a..12324a0 100644 --- a/lib/sidekiq-status/worker.rb +++ b/lib/sidekiq-status/worker.rb @@ -29,7 +29,7 @@ def retrieve(name) def at(num, message = nil) @_status_total = 100 if @_status_total.nil? pct_complete = ((num / @_status_total.to_f) * 100).to_i rescue 0 - store(at: num, total: @_status_total, pct_complete: pct_complete, message: message) + store(at: num, total: @_status_total, pct_complete: pct_complete, message: message, working_at: working_at) end # Sets total number of tasks @@ -37,7 +37,12 @@ def at(num, message = nil) # @return [String] def total(num) @_status_total = num - store(total: num) + store(total: num, working_at: working_at) end + private + + def working_at + @working_at ||= Time.now.to_i + end end diff --git a/spec/lib/sidekiq-status/worker_spec.rb b/spec/lib/sidekiq-status/worker_spec.rb index 5a8d776..3b90843 100644 --- a/spec/lib/sidekiq-status/worker_spec.rb +++ b/spec/lib/sidekiq-status/worker_spec.rb @@ -20,4 +20,22 @@ expect(subject.expiration).to eq(:val) end end + + describe ".at" do + subject { StubJob.new } + + it "records when the worker has started" do + expect { subject.at(0) }.to(change { subject.retrieve('working_at') }) + end + + context "when setting the total for the worker" do + it "records when the worker has started" do + expect { subject.total(100) }.to(change { subject.retrieve('working_at') }) + end + end + + it "records when the worker last worked" do + expect { subject.at(0) }.to(change { subject.retrieve('update_time') }) + end + end end diff --git a/web/views/status.erb b/web/views/status.erb index b3a04d9..0208db1 100644 --- a/web/views/status.erb +++ b/web/views/status.erb @@ -67,6 +67,32 @@ +
+ <% if @status["elapsed"] %> + <%= ChronicDuration.output(@status["elapsed"].to_i, :weeks => true, :units => 2) %> + <% end %> +
++ <% if @status["eta"] %> + <%= ChronicDuration.output(@status["eta"].to_i, :weeks => true, :units => 2) %> + <% end %> +
+