Runtime management of named push notification instances.
Allows starting, stopping, and reconfiguring APNS and FCM instances at runtime, enabling multi-provider setups from a database-backed admin panel.
Usage
# Start an APNS instance
PushX.Instance.start(:apns_prod, :apns,
key_id: "ABC123",
team_id: "TEAM456",
private_key: "-----BEGIN EC PRIVATE KEY-----\n...",
mode: :prod
)
# Start an FCM instance
PushX.Instance.start(:my_fcm, :fcm,
project_id: "my-project",
credentials: %{"type" => "service_account", ...}
)
# Send via instance
PushX.push(:apns_prod, token, msg, topic: "com.example.app")
# Lifecycle management
PushX.Instance.disable(:apns_prod)
PushX.Instance.enable(:apns_prod)
PushX.Instance.reconfigure(:apns_prod, mode: :sandbox)
PushX.Instance.stop(:apns_prod)Credential Rotation Without Restart
Use reconfigure/2 to hot-swap credentials (e.g., after revoking an APNS
.p8 key or rotating an FCM service account). It stops the old pool and
starts a fresh one with new credentials. In-flight requests on the old pool
get connection errors, which the retry logic handles automatically.
# Load new key from database/file/env
new_key = MyApp.Repo.get_latest_apns_key()
PushX.Instance.reconfigure(:apns_prod,
key_id: "NEW_KEY_ID",
private_key: new_key
)
Summary
Functions
Disables an instance. New pushes are rejected, but the pool stays warm.
Re-enables a disabled instance.
Lists all running instances.
Stops and restarts an instance with updated config.
Restarts the Finch HTTP pool for a named instance.
Resolves an instance name to its info for sending.
Starts a named instance.
Returns the status of a named instance.
Stops a named instance and cleans up all resources.
Functions
@spec disable(atom()) :: :ok | {:error, :not_found}
Disables an instance. New pushes are rejected, but the pool stays warm.
@spec enable(atom()) :: :ok | {:error, :not_found}
Re-enables a disabled instance.
@spec list() :: [map()]
Lists all running instances.
Stops and restarts an instance with updated config.
Merges new_config into the existing config. Use this to hot-swap
credentials (e.g., after revoking an APNS .p8 key) without restarting
the application. The old Finch pool is terminated and a new one starts
with fresh connections. In-flight requests on the old pool receive
connection errors, which the retry logic handles automatically.
Examples
# Rotate APNS key
PushX.Instance.reconfigure(:apns_prod,
key_id: "NEW_KEY_ID",
private_key: new_pem_string
)
# Switch APNS environment
PushX.Instance.reconfigure(:apns_prod, mode: :sandbox)
Restarts the Finch HTTP pool for a named instance.
Resolves an instance name to its info for sending.
Returns {:error, :disabled} if the instance exists but is disabled,
{:error, :not_found} if it doesn't exist.
Starts a named instance.
Arguments
name- Unique atom name for this instance (e.g.,:apns_prod)provider-:apnsor:fcmconfig- Provider-specific configuration (keyword list)
APNS Config Keys
:key_id- (required) Apple Key ID:team_id- (required) Apple Team ID:private_key- (required) PEM string,{:file, path}, or{:system, "ENV_VAR"}:mode-:prodor:sandbox(default::prod):pool_size- Finch pool size (default: 2):pool_count- Finch pool count (default: 1)
FCM Config Keys
:project_id- (required) Firebase project ID:credentials- (required) Service account credentials map or JSON string:pool_size- Finch pool size (default: 2):pool_count- Finch pool count (default: 1)
Returns
{:ok, name}on success{:error, :reserved_name}if name is:apnsor:fcm{:error, :already_started}if instance already exists{:error, {:missing_config, keys}}if required config is missing
Returns the status of a named instance.
@spec stop(atom()) :: :ok | {:error, :not_found}
Stops a named instance and cleans up all resources.