Class: OpsBackups::Backup

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
ActionView::Helpers::NumberHelper
Defined in:
app/models/ops_backups/backup.rb,
lib/generators/ops_backups/activeadmin/templates/backup.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.ransackable_attributes(auth_object = nil) ⇒ Object



4
5
6
# File 'lib/generators/ops_backups/activeadmin/templates/backup.rb', line 4

def self.ransackable_attributes(auth_object = nil)
  [ "created_at", "id", "name", "id_value", "tag", "updated_at" ]
end

.retain_last_limit_cleanup_policy(limit: 14, tag: "") ⇒ Object

Keep the last 14 backups



79
80
81
82
83
84
# File 'app/models/ops_backups/backup.rb', line 79

def self.retain_last_limit_cleanup_policy(limit: 14, tag: "")
  records = all
  records = records.where(tag: tag) if tag.present?
  records = records.order(updated_at: :desc).offset(limit)
  records.destroy_all
end

.retain_tiered_cleanup_policy(tag: "") ⇒ Object

Keep all the backups of the last day Keep the last backup of each day in the last week (except the last day) Keep the last backup of each week in the last month (except the last week) Keep the last backup of each month before the last month



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'app/models/ops_backups/backup.rb', line 59

def self.retain_tiered_cleanup_policy(tag: "")
  week = where(created_at: 1.week.ago..1.day.ago)
    .group_by { |b| b.created_at.to_date }
  month = where(created_at: 1.month.ago..1.week.ago)
    .group_by { |b| b.created_at.beginning_of_week }
  older = where(created_at: 1.year.ago..1.month.ago)
    .group_by { |b| b.created_at.beginning_of_month }

  backups = week.merge(month).merge(older)

  ids = backups.flat_map do |_, group|
    group.sort_by(&:created_at).reverse.drop(1).pluck(:id)
  end

  records = where(id: ids)
  records = records.where(tag: tag) if tag.present?
  records.destroy_all
end

Instance Method Details

#db_pg_backup(tag: nil, exclude_tables: []) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'app/models/ops_backups/backup.rb', line 19

def db_pg_backup(tag: nil, exclude_tables: [])
  if ENV["DATABASE_URL"].blank?
    Rails.logger.error("Failed to backup database: DATABASE_URL is not set")
    return
  end

  db_url = ENV["DATABASE_URL"]
  tag ||= exclude_tables.empty? ? "db_pg_full" : "db_pg_partial" # if tag.empty?
  self.tag = tag
  self.name = "pg_#{db_url.split('/').last}_backup_#{Time.now.to_i}.dump"
  save!
  Rails.logger.info("Backing up database")
  # exclude_tables = []
  filename = self.name
  Tempfile.open("pgbackup") do |tempfile|
    begin
      excluded_tables_param = exclude_tables.map { |table| "--exclude-table-data=\#{table}" }.join(" ")
      command = [ "pg_dump", "--no-owner", excluded_tables_param, "-v", "-Fc", "-f", tempfile.path, db_url ].reject(&:empty?)

      stdout, stderr, status = Open3.capture3(*command)

      if status.success?
        Rails.logger.info("PgBackup successful: #{stdout}")
        backup_file.attach io: File.open(tempfile.path), filename:, content_type: "application/octet-stream"
      else
        error_message = "PgBackup failed: #{stderr.strip}"
        Rails.logger.error(error_message)
        raise "PgBackup command failed: #{error_message}"
      end
    rescue StandardError => e
      Rails.logger.error("Failed to backup database: \#{e.message}")
      raise
    end
  end
end

#durationObject



15
16
17
# File 'app/models/ops_backups/backup.rb', line 15

def duration
  Time.at((updated_at - created_at)).utc.strftime("%H:%M:%S")
end

#sizeObject



11
12
13
# File 'app/models/ops_backups/backup.rb', line 11

def size
  backup_file.attached? ? number_to_human_size(backup_file.byte_size) : "N/A"
end