Files
sure/app/models/rule_run.rb
Himank Dave 04549d80bf fix(rules): count blocked rule transactions (#1782)
* Add blocked count to rule run summary

* test(rules): cover rule run blocked counts

* fix(rules): derive blocked count from modified rows

Blocked rule transactions are the processed rows that were not modified. This keeps the displayed queued / processed / modified / blocked summary aligned when a run has already processed all matching rows but some were skipped by enrichment locks.

* fix(rules): count processed rows for rule jobs

Synchronous rule actions return the number of rows they modified, but rule-run processed counts should represent the number of matched transactions the job attempted to process. Using queued matches for processed preserves the distinction between processed and modified rows, which lets locked manual edits appear as blocked instead of making processed collapse to modified.

This changes RuleJob counter semantics, so it was committed separately from the derived blocked-count display change.
2026-05-14 21:56:49 +02:00

47 lines
1.4 KiB
Ruby

class RuleRun < ApplicationRecord
belongs_to :rule
validates :execution_type, inclusion: { in: %w[manual scheduled] }
validates :status, inclusion: { in: %w[pending success failed] }
validates :executed_at, presence: true
validates :transactions_queued, numericality: { greater_than_or_equal_to: 0 }
validates :transactions_processed, numericality: { greater_than_or_equal_to: 0 }
validates :transactions_modified, numericality: { greater_than_or_equal_to: 0 }
validates :pending_jobs_count, numericality: { greater_than_or_equal_to: 0 }
scope :recent, -> { order(executed_at: :desc) }
scope :for_rule, ->(rule) { where(rule: rule) }
scope :successful, -> { where(status: "success") }
scope :failed, -> { where(status: "failed") }
scope :pending, -> { where(status: "pending") }
def pending?
status == "pending"
end
def success?
status == "success"
end
def failed?
status == "failed"
end
def transactions_blocked
[ transactions_processed - transactions_modified, 0 ].max
end
# Thread-safe method to complete a job and update the run
def complete_job!(modified_count: 0)
with_lock do
increment!(:transactions_modified, modified_count)
decrement!(:pending_jobs_count)
# If all jobs are done, mark as success
if pending_jobs_count <= 0
update!(status: "success")
end
end
end
end