| 1 | # frozen_string_literal: true |
| 2 | |
| 3 | # One installation of the siGit Code GitHub App on a github.com account |
| 4 | # (user or org). Synced from `installation` webhooks; soft-deleted on |
| 5 | # uninstall so late-arriving PR webhooks and in-flight jobs no-op instead of |
| 6 | # hitting a missing row. Also caches the short-lived (1h) installation access |
| 7 | # token in-row, so the Puma and jobs processes share it without relying on |
| 8 | # Rails.cache. |
| 9 | class GithubAppInstallation < ApplicationRecord |
| 10 | has_many :github_pr_reviews, dependent: :destroy |
| 11 | |
| 12 | scope :active, -> { where(suspended_at: nil, deleted_at: nil) } |
| 13 | |
| 14 | # Refresh the token when it has less than this long left, so a token that |
| 15 | # expires mid-review can't fail the job. |
| 16 | TOKEN_EXPIRY_MARGIN = 5.minutes |
| 17 | |
| 18 | def active? |
| 19 | suspended_at.nil? && deleted_at.nil? |
| 20 | end |
| 21 | |
| 22 | # The cached installation token, or nil when missing or too close to expiry. |
| 23 | def usable_access_token |
| 24 | return nil if access_token.blank? || access_token_expires_at.blank? |
| 25 | return nil if access_token_expires_at <= TOKEN_EXPIRY_MARGIN.from_now |
| 26 | |
| 27 | access_token |
| 28 | end |
| 29 | |
| 30 | def clear_access_token! |
| 31 | update!(access_token: nil, access_token_expires_at: nil) |
| 32 | end |
| 33 | end |