PhoenixKit.Install.ObanConfig (phoenix_kit v1.7.223)

Copy Markdown View Source

Handles Oban configuration for PhoenixKit installation.

This module provides functionality to:

  • Configure Oban for background job processing
  • Set up required queues (default, file_processing)
  • Add Oban.Plugins.Pruner for job cleanup
  • Add Oban to application supervisor tree
  • Ensure configuration exists during updates

Summary

Functions

Adds or verifies Oban configuration.

Adds Oban to the parent application's supervision tree.

Ensures every notification digest cadence has a crontab entry.

Ensure the Lifeline plugin exists in an existing config :app, Oban block's plugins: list, adding it if missing.

Whether the given config content has a config :app, Oban block that lacks a prefix: key.

Checks if Oban configuration exists in config.exs.

Checks if Oban supervisor is configured in application.ex.

Functions

add_oban_configuration(igniter, prefix \\ nil)

Adds or verifies Oban configuration.

This function ensures that Oban is properly configured for PhoenixKit's background job processing, including:

  1. Repo configuration (auto-detected from PhoenixKit config)
  2. Required queues for file processing
  3. Pruner plugin for automatic job cleanup

Parameters

  • igniter - The igniter context

Returns

Updated igniter with Oban configuration and notices.

add_oban_supervisor(igniter)

Adds Oban to the parent application's supervision tree.

This function ensures that Oban starts automatically when the application starts, with correct positioning in the supervisor tree:

  • AFTER PhoenixKit.Supervisor (PhoenixKit services available)
  • BEFORE Endpoint (Oban ready before HTTP requests)

Important

Oban MUST start AFTER PhoenixKit.Supervisor because PhoenixKit.Supervisor depends on Repo, and Oban also depends on Repo. The correct order is:

  1. Repo (database connection)
  2. PhoenixKit.Supervisor (uses Repo for Settings)
  3. Oban (uses Repo for job persistence)

Parameters

  • igniter - The igniter context

Returns

Updated igniter with Oban added to application supervisor.

ensure_digest_cron_entries(content, app_name)

@spec ensure_digest_cron_entries(String.t(), atom() | String.t()) :: String.t()

Ensures every notification digest cadence has a crontab entry.

Runs AFTER ensure_cron_plugin/2 (which guarantees a crontab: block exists) and is needed because that function short-circuits as soon as ProcessScheduledJobsWorker is present — so a host installed before the digest workers existed would keep a crontab without them forever, and mix phoenix_kit.update would never notice. Each cadence is checked independently, so a partially-updated crontab converges.

Public (not defp, unlike the sibling ensure_*_queue/2 helpers) specifically so this can be unit-tested directly against plain content strings, the same way ensure_lifeline_plugin/2 is.

ensure_lifeline_plugin(content, app_name)

@spec ensure_lifeline_plugin(String.t(), atom() | String.t()) :: String.t()

Ensure the Lifeline plugin exists in an existing config :app, Oban block's plugins: list, adding it if missing.

Rescues a job orphaned in :executing by a hard crash (BEAM kill -9, OOM, node failure) back to :available so it runs again — without it, an orphaned job sits stuck in :executing forever. That's more than a stalled retry: for a unique worker whose unique states: includes :executing (a self-scheduling chain deduping against its own in-flight run is a common pattern — see phoenix_kit_emails' pollers), an orphan permanently blocks every future insert for that worker too, not just the one crashed job.

rescue_after is Oban's default of 60 minutes rather than anything more aggressive, and it must stay above the host's longest-running job. Lifeline rescues purely by elapsed time — it never checks whether the node is still alive — so a job that legitimately runs past rescue_after is flipped back to :available (or :discarded, if its attempts are exhausted) while the original process is still working, and re-executes concurrently. PhoenixKit's longest declared worker timeout is 30 minutes (Storage.Workers.SyncFilesJob); workers with no timeout/1 callback have no bound at all, which is the case the margin is really protecting.

Public (not defp, unlike the sibling ensure_*_queue/2 helpers) specifically so this can be unit-tested directly against plain content strings, the same way oban_block_missing_prefix?/1 is — no live Igniter/Mix context needed.

oban_block_missing_prefix?(content)

@spec oban_block_missing_prefix?(String.t()) :: boolean()

Whether the given config content has a config :app, Oban block that lacks a prefix: key.

Scoped to the Oban block on purpose: a whole-file scan is defeated by the config :phoenix_kit, prefix: "..." entry (which matches a naive prefix: grep) and false-positives on unrelated config. Any prefix: inside the block counts — including computed values like System.get_env(...). Returns false when the content has no Oban block at all (nothing to judge).

oban_config_exists?(igniter)

Checks if Oban configuration exists in config.exs.

Parameters

  • igniter - The igniter context for detecting parent app name

Returns

Boolean indicating if configuration exists.

oban_supervisor_exists?(igniter)

Checks if Oban supervisor is configured in application.ex.

Parameters

  • igniter - The igniter context for detecting parent app name

Returns

Boolean indicating if Oban supervisor exists in application.ex.