class ApplicationJob < ActiveJob::Base # Automatically retry jobs that encountered a deadlock # retry_on ActiveRecord::Deadlocked # Most jobs are safe to ignore if the underlying records are no longer available # discard_on ActiveJob::DeserializationError around_perform do |_job, block| log_entry = create_job_log @job_log = log_entry begin log_entry.update!(status: :running, started_at: Time.current) log("Job started: #{self.class.name}") block.call log("Job completed successfully") log_entry.update!(status: :completed, finished_at: Time.current) rescue => e log("Job failed: #{e.class.name} - #{e.message}") log(e.backtrace.first(5).join("\n")) log_entry.update!( status: :failed, finished_at: Time.current, error_message: "#{e.class.name}: #{e.message}" ) raise end end private def create_job_log server_id = extract_server_id_from_arguments JobLog.create!( job_class: self.class.name, job_id: job_id, arguments: arguments.to_json, server_id: server_id, status: :pending ) end def extract_server_id_from_arguments # First argument is typically server_id for server-related jobs return nil if arguments.empty? arg = arguments.first arg.is_a?(Integer) ? arg : nil end def log(message) return unless @job_log @job_log.append_log(message) end end