Class: ReactOnRailsPro::PreSeedRendererCache

Inherits:
Object
  • Object
show all
Defined in:
lib/react_on_rails_pro/pre_seed_renderer_cache.rb

Overview

Stages the Node Renderer bundle cache in the renderer's expected directory structure (<cache>/<bundleHash>/<bundleHash>.js), including any configured assets_to_copy and, when RSC support is enabled, the RSC bundle and manifests.

Supports two modes:

  • :copy - copies bundle and assets. Designed for Docker image builds where the cache must be baked into an immutable artifact.
  • :symlink - creates relative symlinks to immutable per-ID snapshot files. For same-filesystem workflows (local dev, CI, Heroku-style same-dyno deploys, bundle-caching restores).

Both modes produce the same on-disk cache layout, matching the renderer's runtime contract. The 410->retry cold-start round-trip on first SSR request is eliminated when the pre-seeded bundle is present at renderer startup.

Constant Summary collapse

VALID_MODES =
%i[copy symlink].freeze
CACHE_MUTATION_LOCK_SUFFIX =
".preseed.lock"

Class Method Summary collapse

Class Method Details

.call(mode:) ⇒ Object

mode: is required (no default) because the two modes have fundamentally different semantics — :copy bakes immutable artifacts for Docker/image builds; :symlink links live files on a shared filesystem. Forcing callers to be explicit prevents the footgun where an implicit default would mismatch the deploy context (e.g., copy-mode raises about RENDERER_SERVER_BUNDLE_CACHE_PATH in a dev shell). The rake task and AssetsPrecompile auto-invocation both pass mode: explicitly with their own context-appropriate defaults.



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/react_on_rails_pro/pre_seed_renderer_cache.rb', line 178

def self.call(mode:)
  PreSeedRendererCacheFilesystem.validate_mode!(mode, VALID_MODES)

  cache_dir = PreSeedRendererCacheFilesystem.canonical_cache_dir(resolve_cache_dir(mode))
  action_description = mode == :copy ? "pre-seeding" : "pre-staging"
  artifacts = ReactOnRailsPro::Utils.renderer_artifacts(action_description:)
  puts "[ReactOnRailsPro] Staging renderer cache (mode: #{mode}) in: #{cache_dir}"

  current_hashes, current_generation_manifest_path = with_cache_mutation_lock(cache_dir) do
    hashes = stage_artifacts(artifacts, cache_dir, mode)
    [hashes, PreSeedRendererCacheFilesystem.stage_current_generation_declaration(artifacts, cache_dir)]
  end

  # Previous-deploy staging performs bounded network I/O and uses its own
  # atomic promotion guards. Keep it outside the snapshot critical section
  # so a slow adapter cannot block another process from staging current
  # artifacts or pruning snapshots.
  RollingDeployCacheStager.call(cache_dir:, current_hashes:, mode:)
  puts "[ReactOnRailsPro] Current renderer generation declaration: #{current_generation_manifest_path}"
  current_generation_manifest_path
end