BCUtils.PubSubManager (bc_utils v0.11.0)

Manages Phoenix.PubSub startup to avoid conflicts when multiple applications in the same VM try to start the same PubSub instance.

This module provides utilities to:

  • Check if a PubSub instance is already running
  • Conditionally start PubSub only if needed
  • Provide graceful fallbacks for shared PubSub instances
  • Health check existing PubSub instances

Usage

In your supervision tree:

children = [
  BCUtils.PubSubManager.maybe_child_spec(:my_pubsub),
  # other children...
]
|> Enum.filter(& &1)  # Remove nil entries

Dependencies

This module requires phoenix_pubsub to be available at runtime. Add it to your mix.exs:

{:phoenix_pubsub, "~> 2.1"}

Summary

Functions

Checks if a PubSub instance with the given name is already running.

Ensures a PubSub instance is available, starting it if necessary.

Validates that a PubSub instance is healthy and responding.

Lists all currently running PubSub processes.

Returns a child spec for Phoenix.PubSub if not already started, otherwise nil.

Functions

already_started?(pubsub_name)

@spec already_started?(atom()) :: boolean()

Checks if a PubSub instance with the given name is already running.

This checks both:

  1. Process registry (via Process.whereis/1)
  2. Process health (via Process.alive?/1)

Examples

BCUtils.PubSubManager.already_started?(:my_pubsub)
#=> true | false

ensure_started(pubsub_name, opts \\ [])

@spec ensure_started(
  atom(),
  keyword()
) :: {:ok, pid()} | {:error, term()}

Ensures a PubSub instance is available, starting it if necessary.

This is useful when you need to guarantee PubSub availability outside of a supervision tree context.

Examples

BCUtils.PubSubManager.ensure_started(:my_pubsub)
#=> {:ok, #PID<0.123.0>}

BCUtils.PubSubManager.ensure_started(:my_pubsub, adapter: Phoenix.PubSub.PG2)
#=> {:ok, #PID<0.123.0>}

Returns

  • {:ok, pid} if PubSub is running (existing or newly started)
  • {:error, reason} if unable to start or find PubSub
  • {:error, :phoenix_pubsub_not_available} if Phoenix.PubSub is not loaded

health_check(pubsub_name)

@spec health_check(atom()) :: :ok | {:error, term()}

Validates that a PubSub instance is healthy and responding.

This performs a basic health check by attempting to subscribe and unsubscribe from a test topic.

Examples

BCUtils.PubSubManager.health_check(:my_pubsub)
#=> :ok | {:error, :not_started} | {:error, :unresponsive}

list_running()

@spec list_running() :: [atom()]

Lists all currently running PubSub processes.

This scans the process registry for processes that appear to be Phoenix.PubSub instances.

Examples

BCUtils.PubSubManager.list_running()
#=> [:my_pubsub, :another_pubsub]

maybe_child_spec(pubsub_name, opts \\ [])

@spec maybe_child_spec(
  atom() | nil,
  keyword()
) :: {module(), keyword()} | nil

Returns a child spec for Phoenix.PubSub if not already started, otherwise nil.

This is the recommended way to use this module in supervision trees.

Examples

# Will start PubSub if not running
BCUtils.PubSubManager.maybe_child_spec(:my_pubsub)

# Will return nil if already running
BCUtils.PubSubManager.maybe_child_spec(:my_pubsub)

# Usage in supervision tree
children = [
  BCUtils.PubSubManager.maybe_child_spec(:ex_esdb_pubsub),
  # other children...
]
|> Enum.filter(& &1)  # Remove nil entries

Parameters

  • pubsub_name - The atom name for the PubSub instance, or nil
  • opts - Additional options to pass to Phoenix.PubSub (default: [])

Returns

  • {Phoenix.PubSub, keyword()} - Child spec if PubSub needs to be started
  • nil - If PubSub is already running or pubsub_name is nil