Class: CloudflareUpdatesWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Job, Workers::StatusBroadcastable
Defined in:
app/workers/cloudflare_updates_worker.rb

Overview

Sidekiq worker: cloudflare updates.

Constant Summary collapse

MAX_WAIT_TIME =

Maximum time to wait for downloads (30 minutes)

30.minutes
CHECK_INTERVAL =

Check status every 30 seconds

30.seconds
MAX_CHECKS =

Maximum number of checks

(MAX_WAIT_TIME / CHECK_INTERVAL).to_i

Instance Attribute Summary

Attributes included from Workers::StatusBroadcastable

#broadcast_status_updates

Instance Method Summary collapse

Methods included from Workers::StatusBroadcastable::Overrides

#at, #store, #total

Instance Method Details

#perform(video_id, options = {}) ⇒ Object

Note:

the options normalization inside is redundant with
Sidekiq::NormalizeArgsMiddleware::Server (see lib/sidekiq/), but is left in
place until this already-over-limit method is decomposed. Remove it as part
of that focused refactor.

Parameters:

  • video_id (Integer)

    ID of the Video to update on Cloudflare

  • options (Hash) (defaults to: {})

    job options (symbolized internally)

Options Hash (options):

  • redirect_path (String)

    path to redirect to when the job completes

  • default_download_action (String)

    'enable' or 'disable' the default MP4 download

  • audio_download_action (String)

    'enable' or 'disable' the audio download

  • vtt_captions_en_action (String)

    'enable' or 'disable' English VTT captions

  • vtt_captions_LOCALE_action (String)

    'enable' or 'disable' translated VTT captions per supported locale (e.g. vtt_captions_es_action)



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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'app/workers/cloudflare_updates_worker.rb', line 27

def perform(video_id, options = {})
  @video = Video.find(video_id)
  @options = options.symbolize_keys
  @redirect_path = @options[:redirect_path] || "#{CRM_URL}/videos/#{@video.id}"
  @start_time = Time.current

  # Set initial status
  total(100)
  at(0, 'Starting Cloudflare updates...')

  begin
    # Step 1: Refresh Cloudflare data to get latest metadata (including duration and download status)
    at(5, 'Refreshing Cloudflare data...')
    @video.refresh_cloudflare_data
    at(10, 'Cloudflare data refreshed')

    # Step 2: Extract poster frame at 5 seconds for better visual representation
    at(12, 'Extracting poster frame at 5 seconds...')
    @video.extract_poster_at_timestamp(5.0)
    at(15, 'Poster extraction completed')

    # Step 3: Handle default video download action
    case @options[:default_download_action]
    when 'enable'
      at(20, 'Enabling default video download...')
      raise 'Failed to enable default video download' unless @video.enable_mp4_download('default').success?

      at(25, 'Default video download enabled, waiting for processing...')
      wait_for_download_ready('default', 25, 45) # 25-45% range
    when 'disable'
      at(20, 'Deleting default video download...')
      @video.delete_mp4_download('default')
      at(45, 'Default video download deleted')
    else
      at(45, 'Skipping default video download...')
    end

    # Step 4: Handle audio download action
    case @options[:audio_download_action]
    when 'enable'
      at(50, 'Enabling audio download...')
      raise 'Failed to enable audio download' unless @video.enable_mp4_download('audio').success?

      at(55, 'Audio download enabled, waiting for processing...')
      wait_for_download_ready('audio', 55, 75) # 55-75% range
    when 'disable'
      at(50, 'Deleting audio download...')
      @video.delete_mp4_download('audio')
      at(75, 'Audio download deleted')
    else
      at(75, 'Skipping audio download...')
    end

    # Step 5: Handle VTT captions actions
    caption_service = CloudflareVttService.new(@video)
    performed_any_caption_action = false

    # Handle English captions action
    case @options[:vtt_captions_en_action]
    when 'enable'
      at(80, 'Uploading English VTT captions to Cloudflare...')
      caption_service.upload_vtt_captions_en
      at(82, 'English VTT captions uploaded successfully')
      performed_any_caption_action = true
    when 'disable'
      at(80, 'Deleting English VTT captions from Cloudflare...')
      caption_service.delete_vtt_captions('en')
      at(82, 'English VTT captions deleted successfully')
      performed_any_caption_action = true
    end

    # Handle translated captions for each available locale
    current_progress = 82
    progress_per_locale = 3.0 / VideoProcessing::VideoTranslationService::SUPPORTED_LOCALES.keys.length

    VideoProcessing::VideoTranslationService::SUPPORTED_LOCALES.each do |locale, info|
      action_key = :"vtt_captions_#{locale.underscore}_action"
      action = @options[action_key]

      case action
      when 'enable'
        at(current_progress.round, "Uploading #{info[:name]} VTT captions to Cloudflare...")
        caption_service.upload_vtt_captions_translated(locale)
        at((current_progress + progress_per_locale).round, "#{info[:name]} VTT captions uploaded successfully")
        performed_any_caption_action = true
      when 'disable'
        at(current_progress.round, "Deleting #{info[:name]} VTT captions from Cloudflare...")
        caption_service.delete_vtt_captions(locale)
        at((current_progress + progress_per_locale).round, "#{info[:name]} VTT captions deleted successfully")
        performed_any_caption_action = true
      end

      current_progress += progress_per_locale
    end

    at(85, 'Skipping VTT captions...') unless performed_any_caption_action

    # Step 6: Refresh Cloudflare data again to get updated download status
    at(90, 'Performing final status refresh...')
    @video.refresh_cloudflare_data
    at(95, 'All updates verified!')

    # Complete
    store status: 'completed'
    at(100, 'Cloudflare updates completed successfully!')
    store redirect_to: @redirect_path
  rescue StandardError => e
    error_message = e.message
    Rails.logger.error "Cloudflare updates failed for video #{@video.id}: #{error_message}"
    Rails.logger.error e.backtrace.join("\n")

    # Store failure status and error message for the job progress page
    store status: 'failed'
    store error_message: error_message
    store redirect_to: @redirect_path

    # Report to AppSignal
    ErrorReporting.error(e, source: :background, video_id: @video.id)
  end
end