diff --git a/app/controllers/good_job/performances_controller.rb b/app/controllers/good_job/performances_controller.rb new file mode 100644 index 000000000..8410c2b32 --- /dev/null +++ b/app/controllers/good_job/performances_controller.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +module GoodJob + class PerformancesController < GoodJob::ApplicationController + def index + end + end +end diff --git a/app/filters/good_job/executions_filter.rb b/app/filters/good_job/executions_filter.rb new file mode 100644 index 000000000..63a1b8cf2 --- /dev/null +++ b/app/filters/good_job/executions_filter.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true +module GoodJob + class PerformanceFilter < BaseFilter + DURATIONS = { + "2h" => '1 minute', + "24h" => '10 minutes', + "3d" => '1 hour', + "7d" => '2 hours', + "14d" => '4 hours', + "30d" => '12 hours', + "90d" => '1 day', + }.freeze + + def states + { + 'scheduled' => base_query.scheduled.count, + 'queued' => base_query.queued.count, + 'running' => base_query.running.count, + 'succeeded' => base_query.succeeded.count, + 'errored' => base_query.errored.count, + } + end + + def filtered_query + query = base_query.includes(:executions).includes_advisory_locks + + query = query.job_class(params[:job_class]) if params[:job_class].present? + query = query.where(queue_name: params[:queue_name]) if params[:queue_name].present? + query = query.search_text(params[:query]) if params[:query].present? + query = query.where(cron_key: params[:cron_key]) if params[:cron_key].present? + + if params[:state] + case params[:state] + when 'discarded' + query = query.discarded + when 'finished' + query = query.finished + when 'retried' + query = query.retried + when 'scheduled' + query = query.scheduled + when 'running' + query = query.running.select("#{GoodJob::Job.table_name}.*", 'pg_locks.locktype') + when 'queued' + query = query.queued + end + end + + query + end + + def default_base_query + GoodJob::Execution.all + end + end +end diff --git a/app/models/good_job/execution.rb b/app/models/good_job/execution.rb index 2d91f3115..9cd6110d8 100644 --- a/app/models/good_job/execution.rb +++ b/app/models/good_job/execution.rb @@ -142,23 +142,16 @@ def self.queue_parser(string) # @return [ActiveRecord::Relation] scope :schedule_ordered, -> { order(Arel.sql('COALESCE(scheduled_at, created_at) ASC')) } - # Get Jobs were completed before the given timestamp. If no timestamp is - # provided, get all jobs that have been completed. By default, GoodJob - # destroys jobs after they are completed and this will find no jobs. - # However, if you have changed {GoodJob.preserve_job_records}, this may - # find completed Jobs. - # @!method finished(timestamp = nil) - # @!scope class - # @param timestamp (Float) - # Get jobs that finished before this time (in epoch time). - # @return [ActiveRecord::Relation] - scope :finished, ->(timestamp = nil) { timestamp ? where(arel_table['finished_at'].lteq(timestamp)) : where.not(finished_at: nil) } - - # Get Jobs that started but not finished yet. - # @!method running - # @!scope class - # @return [ActiveRecord::Relation] - scope :running, -> { where.not(performed_at: nil).where(finished_at: nil) } + # First execution will run in the future + scope :scheduled, -> { where(finished_at: nil).where('COALESCE(scheduled_at, created_at) > ?', DateTime.current).where("(serialized_params->>'executions')::integer < 2") } + # Immediate/Scheduled time to run has passed, waiting for an available thread run + scope :queued, -> { where(finished_at: nil).where('COALESCE(scheduled_at, created_at) <= ?', DateTime.current).joins_advisory_locks.where(pg_locks: { locktype: nil }) } + # Advisory locked and executing + scope :running, -> { where(finished_at: nil).joins_advisory_locks.where.not(pg_locks: { locktype: nil }) } + # Completed executing successfully + scope :finished, -> { where.not(finished_at: nil).where(error: nil) } + # Errored but will not be retried + scope :errored, -> { where.not(finished_at: nil).where.not(error: nil) } # Get Jobs that do not have subsequent retries # @!method running diff --git a/app/views/good_job/performances/index.html.erb b/app/views/good_job/performances/index.html.erb new file mode 100644 index 000000000..e69de29bb diff --git a/config/routes.rb b/config/routes.rb index 8b433eece..9fdb8474d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,6 +2,8 @@ GoodJob::Engine.routes.draw do root to: redirect(path: 'jobs') + resources :performance, only: %i[index] + resources :jobs, only: %i[index show destroy] do collection do get :mass_update, to: redirect(path: 'jobs')