| 1 | # frozen_string_literal: true |
| 2 | |
| 3 | # One automated review of one head SHA of one github.com pull request. The |
| 4 | # unique (repo, pr, sha) index is the idempotency guard: GithubPrReviewJob |
| 5 | # claims a row with create_or_find_by before doing any work, so webhook |
| 6 | # redeliveries and rapid `synchronize` storms collapse into a single review. |
| 7 | class GithubPrReview < ApplicationRecord |
| 8 | belongs_to :github_app_installation |
| 9 | |
| 10 | enum :status, %w[pending running completed failed skipped].index_by(&:itself) |
| 11 | |
| 12 | # A `running` row normally means another execution owns this SHA — but a |
| 13 | # worker killed mid-review (deploys kill -9) would leave the row running |
| 14 | # forever, so treat a long-stale claim as abandoned and re-enter. |
| 15 | STALE_RUNNING_AFTER = 30.minutes |
| 16 | |
| 17 | def claimable? |
| 18 | pending? || (running? && started_at.present? && started_at < STALE_RUNNING_AFTER.ago) |
| 19 | end |
| 20 | |
| 21 | def skip!(reason) |
| 22 | update!(status: "skipped", skip_reason: reason, completed_at: Time.current) |
| 23 | end |
| 24 | end |