Packages
phoenix_kit
1.7.20
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/modules/emails/supervisor.ex
defmodule PhoenixKit.Modules.Emails.Supervisor do
@moduledoc """
Supervisor for PhoenixKit email tracking system.
This module manages all processes necessary for email tracking:
- SQS Worker for processing events from AWS SQS
- Additional processes (metrics, archiving, etc.)
## Integration into Parent Application
Add supervisor to your application's supervision tree:
# In lib/your_app/application.ex
def start(_type, _args) do
children = [
# ... your other processes
# PhoenixKit Email Tracking
PhoenixKit.Modules.Emails.Supervisor
]
opts = [strategy: :one_for_one, name: YourApp.Supervisor]
Supervisor.start_link(children, opts)
end
## Configuration
Supervisor automatically reads settings from PhoenixKit Settings:
- `sqs_polling_enabled` - enable/disable SQS Worker
- `sqs_polling_interval_ms` - polling interval
- other SQS settings
## Process Management
# Stop SQS Worker
PhoenixKit.Modules.Emails.SQSWorker.pause()
# Start SQS Worker
PhoenixKit.Modules.Emails.SQSWorker.resume()
# Check status
PhoenixKit.Modules.Emails.SQSWorker.status()
## Monitoring
Supervisor provides information about process state:
# Get list of child processes
Supervisor.which_children(PhoenixKit.Modules.Emails.Supervisor)
# Get process count
Supervisor.count_children(PhoenixKit.Modules.Emails.Supervisor)
"""
use Supervisor
require Logger
alias PhoenixKit.Modules.Emails
alias PhoenixKit.Modules.Emails.SQSPollingManager
alias PhoenixKit.Modules.Emails.SQSWorker
@doc """
Starts supervisor for email tracking system.
## Options
- `:name` - supervisor process name (defaults to `__MODULE__`)
## Examples
{:ok, pid} = PhoenixKit.Modules.Emails.Supervisor.start_link()
"""
def start_link(opts \\ []) do
name = Keyword.get(opts, :name, __MODULE__)
Supervisor.start_link(__MODULE__, opts, name: name)
end
@doc false
def init(_opts) do
children = build_children()
# Start initial SQS polling job if enabled
start_initial_sqs_polling_job()
# Use :one_for_one strategy - if one process crashes,
# only that one is restarted
Supervisor.init(children, strategy: :one_for_one)
end
@doc """
Returns information about email tracking system status.
## Examples
iex> PhoenixKit.Modules.Emails.Supervisor.system_status()
%{
supervisor_running: true,
sqs_worker_running: true,
sqs_worker_status: %{polling_enabled: true, ...},
children_count: 1
}
"""
def system_status(supervisor \\ __MODULE__) do
children = Supervisor.which_children(supervisor)
child_count = Supervisor.count_children(supervisor)
sqs_worker_running =
Enum.any?(children, fn {id, _pid, _type, _modules} ->
id == SQSWorker
end)
sqs_worker_status =
if sqs_worker_running do
try do
SQSWorker.status()
catch
_, _ -> %{error: "worker_not_responding"}
end
else
%{error: "worker_not_started"}
end
%{
supervisor_running: true,
sqs_worker_running: sqs_worker_running,
sqs_worker_status: sqs_worker_status,
children_count: child_count.active,
total_restarts: child_count.workers
}
catch
_, _ ->
%{
supervisor_running: false,
error: "supervisor_not_accessible"
}
end
@doc """
Stops and restarts SQS Worker.
Useful for applying new configuration settings.
## Examples
iex> PhoenixKit.Modules.Emails.Supervisor.restart_sqs_worker()
:ok
"""
def restart_sqs_worker(supervisor \\ __MODULE__) do
case Supervisor.terminate_child(supervisor, SQSWorker) do
:ok ->
case Supervisor.restart_child(supervisor, SQSWorker) do
{:ok, _pid} -> :ok
{:ok, _pid, _info} -> :ok
{:error, reason} -> {:error, reason}
end
{:error, reason} ->
{:error, reason}
end
end
## --- Helper Functions for Integration ---
@doc """
Returns child spec for integration into parent supervisor.
This function is used when you want more precise control
over email tracking integration in your application.
## Examples
# In lib/your_app/application.ex
def start(_type, _args) do
children = [
# ... other processes
PhoenixKit.Modules.Emails.Supervisor.child_spec([])
]
Supervisor.start_link(children, strategy: :one_for_one)
end
"""
def child_spec(opts) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [opts]},
type: :supervisor,
restart: :permanent,
shutdown: :infinity
}
end
## --- Private Functions ---
# Builds list of child processes based on configuration
defp build_children do
children = []
# Add SQS Worker if polling is enabled
children =
if should_start_sqs_worker?() do
[build_sqs_worker_spec() | children]
else
children
end
# In the future, other processes can be added here:
# - Metrics collector
# - Archiving worker
# - Cleanup scheduler
children
end
# Checks whether SQS Worker should start
defp should_start_sqs_worker? do
# Check that email tracking is enabled
# Check that AWS SES events processing is enabled
# Check that SQS polling is enabled
# Check that SQS settings exist
Emails.enabled?() &&
Emails.ses_events_enabled?() &&
Emails.sqs_polling_enabled?() &&
has_sqs_configuration?()
end
# Checks for minimum SQS configuration
defp has_sqs_configuration? do
sqs_config = Emails.get_sqs_config()
not is_nil(sqs_config.queue_url) and
sqs_config.queue_url != ""
end
# Creates child spec for SQS Worker
defp build_sqs_worker_spec do
%{
id: SQSWorker,
start: {SQSWorker, :start_link, [[]]},
type: :worker,
restart: :permanent,
# 10 seconds for graceful shutdown
shutdown: 10_000
}
end
# Start initial SQS polling job if enabled
# Uses spawn to defer job creation until Oban is ready
defp start_initial_sqs_polling_job do
if should_start_oban_polling?() do
# Spawn a process that waits for Oban to be ready before creating the job
spawn(fn ->
# Wait for Oban to start (max 10 attempts with 500ms delay)
wait_for_oban(10, 500)
Logger.info("Email Supervisor: Starting initial SQS polling job via Oban")
case SQSPollingManager.enable_polling() do
{:ok, job} ->
Logger.info("Email Supervisor: Initial SQS polling job started", %{job_id: job.id})
{:error, reason} ->
Logger.warning("Email Supervisor: Failed to start initial SQS polling job", %{
reason: inspect(reason)
})
end
end)
end
end
# Wait for Oban to be available
defp wait_for_oban(0, _delay), do: :timeout
defp wait_for_oban(attempts, delay) do
case Oban.Registry.config(Oban) do
%Oban.Config{} ->
:ok
end
catch
_, _ ->
Process.sleep(delay)
wait_for_oban(attempts - 1, delay)
end
# Check if Oban-based polling should start
defp should_start_oban_polling? do
Emails.enabled?() &&
Emails.ses_events_enabled?() &&
Emails.sqs_polling_enabled?() &&
has_sqs_configuration?()
end
end