mirror of
https://github.com/System-End/hackatime.git
synced 2026-04-19 16:38:23 +00:00
* Imports are back!! * Settings UI v3 * Use Inertia forms for heartbeat imports * Update app/javascript/pages/Users/Settings/Data.svelte Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update Bundle * Fix broken Form/Button markup in Data.svelte settings page * Update JS deps * Greptile fixes * Remove dead code --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
88 lines
2.1 KiB
Ruby
88 lines
2.1 KiB
Ruby
class HeartbeatImportRun < ApplicationRecord
|
|
COOLDOWN = 4.hours
|
|
|
|
TERMINAL_STATES = %w[completed failed].freeze
|
|
ACTIVE_STATES = %w[queued requesting_dump waiting_for_dump downloading_dump importing].freeze
|
|
REMOTE_SOURCE_KINDS = %w[wakatime_dump hackatime_v1_dump].freeze
|
|
|
|
belongs_to :user
|
|
|
|
encrypts :encrypted_api_key, deterministic: false
|
|
|
|
enum :source_kind, {
|
|
dev_upload: 0,
|
|
wakatime_dump: 1,
|
|
hackatime_v1_dump: 2
|
|
}
|
|
|
|
enum :state, {
|
|
queued: 0,
|
|
requesting_dump: 1,
|
|
waiting_for_dump: 2,
|
|
downloading_dump: 3,
|
|
importing: 4,
|
|
completed: 5,
|
|
failed: 6
|
|
}
|
|
|
|
validates :encrypted_api_key, presence: true, on: :create, unless: :dev_upload?
|
|
|
|
scope :latest_first, -> { order(created_at: :desc) }
|
|
scope :active_imports, -> { where(state: states.values_at(*ACTIVE_STATES)) }
|
|
scope :remote_imports, -> { where(source_kind: source_kinds.values_at(*REMOTE_SOURCE_KINDS)) }
|
|
|
|
def remote?
|
|
!dev_upload?
|
|
end
|
|
|
|
def terminal?
|
|
TERMINAL_STATES.include?(state)
|
|
end
|
|
|
|
def active_import?
|
|
ACTIVE_STATES.include?(state)
|
|
end
|
|
|
|
def cooldown_until
|
|
return nil if remote_requested_at.blank?
|
|
|
|
remote_requested_at + COOLDOWN
|
|
end
|
|
|
|
def progress_percent
|
|
return 100 if completed?
|
|
|
|
if waiting_for_dump? || downloading_dump? || requesting_dump?
|
|
return remote_percent_complete.to_f.clamp(0, 100).round
|
|
end
|
|
|
|
return 0 unless total_count.to_i.positive?
|
|
|
|
((processed_count.to_f / total_count.to_f) * 100).clamp(0, 100).round
|
|
end
|
|
|
|
def clear_sensitive_fields!
|
|
update_columns(encrypted_api_key: nil, updated_at: Time.current)
|
|
end
|
|
|
|
def self.active_for(user)
|
|
where(user: user).active_imports.latest_first.first
|
|
end
|
|
|
|
def self.latest_for(user)
|
|
where(user: user).latest_first.first
|
|
end
|
|
|
|
def self.remote_cooldown_until_for(user)
|
|
latest_remote_request = where(user: user)
|
|
.remote_imports
|
|
.where.not(remote_requested_at: nil)
|
|
.order(remote_requested_at: :desc)
|
|
.pick(:remote_requested_at)
|
|
|
|
return nil if latest_remote_request.blank?
|
|
|
|
retry_at = latest_remote_request + COOLDOWN
|
|
retry_at.future? ? retry_at : nil
|
|
end
|
|
end
|