Class: Jobs::MigrateBadgeImageToUploads

Inherits:
Onceoff show all
Defined in:
app/jobs/onceoff/migrate_badge_image_to_uploads.rb

Instance Method Summary collapse

Methods inherited from Onceoff

enqueue_all, #execute, name_for, #running_key_name

Methods inherited from Base

acquire_cluster_concurrency_lock!, clear_cluster_concurrency_lock!, cluster_concurrency, cluster_concurrency_redis_key, delayed_perform, #error_context, #execute, get_cluster_concurrency, #last_db_duration, #log, #perform, #perform_immediately

Instance Method Details

#execute_onceoff(args) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'app/jobs/onceoff/migrate_badge_image_to_uploads.rb', line 6

def execute_onceoff(args)
  column_exists = DB.exec(<<~SQL) == 1
    SELECT 1
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE
      table_schema = 'public' AND
      table_name = 'badges' AND
      column_name = 'image_upload_id'
  SQL
  return unless column_exists

  Badge
    .where.not(image: nil)
    .select(:id, :image_upload_id, :image)
    .each do |badge|
      if badge.image_upload.present?
        DB.exec("UPDATE badges SET image = NULL WHERE id = ?", badge.id)
        next
      end

      image_url = badge[:image]
      next if image_url.blank? || image_url !~ URI.regexp

      count = 0
      file = nil
      sleep_interval = 5

      loop do
        url = UrlHelper.absolute_without_cdn(image_url)

        begin
          file =
            FileHelper.download(
              url,
              max_file_size: [SiteSetting.max_image_size_kb.kilobytes, 20.megabytes].max,
              tmp_file_name: "tmp_badge_image_upload",
              skip_rate_limit: true,
              follow_redirect: true,
            )
        rescue OpenURI::HTTPError,
               OpenSSL::SSL::SSLError,
               Net::OpenTimeout,
               Net::ReadTimeout,
               Errno::ECONNREFUSED,
               EOFError,
               SocketError,
               Discourse::InvalidParameters => e
          logger.error(
            "Error encountered when trying to download from URL '#{image_url}' " +
              "for badge '#{badge[:id]}'.\n#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}",
          )
        end

        count += 1
        break if file

        logger.warn(
          "Failed to download image from #{url} for badge '#{badge[:id]}'. Retrying (#{count}/3)...",
        )
        break if count >= 3
        sleep(count * sleep_interval)
      end

      next if file.blank?

      upload =
        UploadCreator.new(
          file,
          "image_for_badge_#{badge[:id]}",
          origin: UrlHelper.absolute(image_url),
        ).create_for(Discourse.system_user.id)

      if upload.errors.count > 0 || upload&.id.blank?
        logger.error(
          "Failed to create an upload for the image of badge '#{badge[:id]}'. Error: #{upload.errors.full_messages}",
        )
      else
        DB.exec(
          "UPDATE badges SET image = NULL, image_upload_id = ? WHERE id = ?",
          upload.id,
          badge[:id],
        )
      end
    end
end