Module: ActiveStorage::HotCell::Client

Defined in:
lib/active_storage/hot_cell/client.rb,
lib/active_storage/hot_cell/client/railtie.rb,
lib/active_storage/hot_cell/client/version.rb,
lib/active_storage/hot_cell/client/operations.rb,
lib/active_storage/hot_cell/client/previewers/pdf.rb,
lib/active_storage/hot_cell/client/tool_arguments.rb,
lib/active_storage/hot_cell/client/analyzers/audio.rb,
lib/active_storage/hot_cell/client/analyzers/image.rb,
lib/active_storage/hot_cell/client/analyzers/video.rb,
lib/active_storage/hot_cell/client/analyzers/probing.rb,
lib/active_storage/hot_cell/client/analyzers/analyzing.rb,
lib/active_storage/hot_cell/client/analyzers/image/vips.rb,
lib/active_storage/hot_cell/client/previewers/pdf/mutool.rb,
lib/active_storage/hot_cell/client/previewers/previewing.rb,
lib/active_storage/hot_cell/client/analyzers/image/magick.rb,
lib/active_storage/hot_cell/client/previewers/pdf/poppler.rb,
lib/active_storage/hot_cell/client/analyzers/audio/ffprobe.rb,
lib/active_storage/hot_cell/client/analyzers/video/ffprobe.rb,
lib/active_storage/hot_cell/client/previewers/video/ffmpeg.rb,
lib/active_storage/hot_cell/client/transformers/image/vips.rb,
lib/active_storage/hot_cell/client/transformers/image/magick.rb,
lib/active_storage/hot_cell/client/transformers/transforming.rb

Overview

Everything the application side defines lives under this, and everything the cell side defines lives under ActiveStorage::HotCell::Server. Not a tidying convention: the two gems are never both loaded in production, and a cell is forked from a process that may well have loaded this one — after which a shared name is a superclass mismatch while the cell boots. Two namespaces make that impossible rather than avoided.

Defined Under Namespace

Modules: Analyzers, Operations, Previewers, ToolArguments, Transformers Classes: Railtie

Constant Summary collapse

JOBS =

These four jobs declare retry_on ActiveStorage::IntegrityError and nothing else, and ActiveJob does not retry by default. They should retry the transient class too: capacity most obviously, and every other transient verdict. The policy matches the one they already declare, so a cell failure and an integrity failure back off the same way.

Which of these classes exists depends on the Rails version, so a name that is not loaded is skipped.

%w[
  ActiveStorage::AnalyzeJob
  ActiveStorage::CreateVariantsJob
  ActiveStorage::PreviewImageJob
  ActiveStorage::TransformJob
].freeze
RETRY =
{ wait: :polynomially_longer, attempts: 10 }.freeze
CLIENTS =

The clients this gem ships, which is where the retry hook learns which cells' transient classes the jobs must retry. Deliberately not HotCell.clients: that records every client the process loaded, including an application's own for unrelated cells, and Active Storage's jobs have no business retrying those.

[ Operations::Transformers::Image::Vips, Operations::Transformers::Image::Magick,
Operations::Analyzers::Image::Vips, Operations::Analyzers::Image::Magick,
Operations::Analyzers::Media::Ffprobe,
Operations::Previewers::Pdf::Mutool, Operations::Previewers::Pdf::Poppler,
Operations::Previewers::Video::Ffmpeg ].freeze
VERSION =
"0.1.0"
CELL =

The cell these all talk to by default. An application registers it under this name.

"active_storage"

Class Method Summary collapse

Class Method Details

.retry_transient_failures!(jobs: JOBS) ⇒ Object

The railtie calls this from a to_prepare block. Applied once at boot it would not survive a code reload: a gem engine's app/jobs is in the reloadable autoloader, so these classes are discarded and redefined, and the retry would silently disappear after the first file save in development.

Every registered cell contributes its transient class, because the documented multi-cell arrangement routes PreviewVideo to a cell of its own and each cell names its own class. A cell not yet registered contributes nothing rather than raising: this runs on the boot where the application has bundled the gem and not yet written the initializer, and that boot has to succeed for the rollout to take two deploys rather than one.



61
62
63
64
65
66
67
68
# File 'lib/active_storage/hot_cell/client.rb', line 61

def retry_transient_failures!(jobs: JOBS)
  transients = CLIENTS.filter_map { |client| client.cell.transient if client.registered? }
                      .uniq
  return [] if transients.empty?

  jobs.filter_map(&:safe_constantize)
      .each { |job| job.retry_on(*transients, **RETRY) }
end