Module: Postburner::Execution

Extended by:
ActiveSupport::Concern
Included in:
Job
Defined in:
app/concerns/postburner/execution.rb

Overview

Concern providing job execution methods for Postburner jobs.

Handles the full job execution lifecycle including validation, callbacks, timing tracking, error handling, and state management. Provides both the class-level entry point for workers and the instance-level execution logic.

Examples:

Direct execution

Postburner::Job.perform(job.id)

Instance execution

job.perform!(job.args)

Instance Method Summary collapse

Instance Method Details

#perform!(args = {}) ⇒ void

Note:

Does not execute if queued_at is nil, in the future, already processed, or removed

Note:

Premature execution (before run_at) is delegated to queue strategy

This method returns an undefined value.

Executes the job with full lifecycle management and error handling.

This is the main execution method called by Postburner workers or test strategies. Performs validation checks, executes callbacks, calls the subclass #perform method, tracks timing and statistics, and handles errors.

Execution flow:

  1. Runs attempt callbacks (fires on every retry)

  2. Updates attempting metadata (attempting_at, attempts, lag)

  3. Validates job state (queued, not processed, not removed, not premature)

  4. Runs processing callbacks

  5. Calls subclass #perform method

  6. Runs processed callbacks (only on success)

  7. Updates completion metadata (processed_at, duration)

  8. Logs and tracks any exceptions

Parameters:

  • args (Hash) (defaults to: {})

    Arguments to pass to #perform method

Raises:

  • (Exception)

    Any exception raised by #perform is logged and re-raised

See Also:



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'app/concerns/postburner/execution.rb', line 94

def perform!(args={})
  run_callbacks :attempt do
    self.attempting

    self.update_columns(
      attempting_at:  self.attempting_at,
      attempts:       self.attempts,
      attempt_count:  self.attempts.length,
      lag:            self.lag,
      processing_at:  Time.current,
    )

    begin
      if self.queued_at.nil?
        self.log! "Not Queued", level: :error
        return
      end

      if self.queued_at > Time.current
        self.log! "Future Queued", level: :error
        return
      end

      if self.processed_at.present?
        self.log! "Already Processed", level: :error
        self.delete!
        return
      end

      if self.removed_at.present?
        self.log! "Removed", level: :error
        return
      end

      if self.run_at && self.run_at.to_i > Time.current.to_i
        Postburner.queue_strategy.handle_premature_perform(self)
        return
      end

      self.log!("START (bkid #{self.bkid})")

      run_callbacks :processing do
        begin
          method(:perform).arity == 0 ? self.perform : self.perform(args)
        rescue Exception => exception
          self.persist_metadata!
          self.log! '[Postburner] Exception raised during perform prevented completion.'
          raise exception
        end
      end

      self.log!("DONE (bkid #{self.bkid})")

      begin
        now = Time.current
        _duration =  (now - self.processing_at) * 1000 rescue nil

        run_callbacks :processed do
          persist_metadata!(
            processed_at: now,
            duration:     _duration,
          )
        end
      rescue Exception => e
        self.log_exception!(e)
        self.log! '[Postburner] Could not set data after processing.'
        # TODO README doesn't retry if Postburner is to blame
      end

    rescue Exception => exception
      self.log_exception!(exception)
      handle_retry_or_raise(exception)
    end
  end # run_callbacks :attempt

end