Class: InstagramConnect::FetchMediaJob
- Inherits:
-
ApplicationJob
- Object
- ActiveJob::Base
- ApplicationJob
- InstagramConnect::FetchMediaJob
- Defined in:
- app/jobs/instagram_connect/fetch_media_job.rb
Overview
Copies one inbound attachment's bytes out of Meta's CDN and into the host's own storage.
This runs against a clock nobody controls: Instagram's media URLs expire and there is no endpoint to ask for a fresh one. So a failure here is permanent for that file, which is why the retry ladder ends in a terminal state rather than leaving the row pending — a pending attachment renders as a loading placeholder, and one that never resolves is worse than an honest "this file is no longer available".
Constant Summary collapse
- TIMEOUT =
30- TRANSPORT_ERRORS =
[ Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Net::OpenTimeout, Net::ReadTimeout, SocketError, IOError ].freeze
Class Method Summary collapse
-
.exhausted(attachment_id, error) ⇒ Object
Retries are spent.
Instance Method Summary collapse
Class Method Details
.exhausted(attachment_id, error) ⇒ Object
Retries are spent. Without this the job would land in the dead set and leave the attachment pending for ever — a loading placeholder in the thread that nothing will ever resolve.
29 30 31 |
# File 'app/jobs/instagram_connect/fetch_media_job.rb', line 29 def self.exhausted(, error) MessageAttachment.find_by(id: )&.mark_unavailable!("transport:#{error.class}") end |
Instance Method Details
#perform(attachment_id) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'app/jobs/instagram_connect/fetch_media_job.rb', line 33 def perform() = MessageAttachment.find_by(id: ) return if .nil? return unless storage_available? # The guard and the write have to be one atomic step: two deliveries of # the same webhook would otherwise both see "pending" and both fetch. .with_lock do next unless .fetchable? fetch_into() end end |