notifications
notifications
codex_platform.notifications
Building blocks for notification delivery.
# Contracts / DTOs
from codex_platform.notifications import NotificationPayloadDTO, NotificationRecipient
from codex_platform.notifications import NotificationChannel
# Channel pipeline
from codex_platform.notifications import AsyncEmailClient
from codex_platform.notifications import BaseDeliveryOrchestrator, ChannelRegistry
# Delivery adapters (how payload gets to the pipeline)
from codex_platform.notifications.delivery import ArqNotificationAdapter
from codex_platform.notifications.delivery import DirectNotificationAdapter
# Template rendering (requires jinja2 — install separately)
from codex_platform.notifications.renderer import TemplateRenderer
Classes
NotificationChannel
Bases: StrEnum
Supported notification delivery channel identifiers.
Source code in src/codex_platform/notifications/channels.py
AsyncEmailClient
Async SMTP email sender. Implements DeliveryChannel.
Usage
client = AsyncEmailClient( smtp_host="mail.example.com", smtp_port=465, smtp_user="user", smtp_password="pass", # pragma: allowlist secret smtp_from_email="noreply@example.com", ) success = await client.send( to="user@example.com", subject="Hello", html_content="Hi", text_content="Hi", )
Source code in src/codex_platform/notifications/clients/smtp.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | |
Functions
is_available()
send(to, subject, html_content, text_content, timeout=15)
async
Send email via SMTP.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
to
|
str
|
Recipient email address. |
required |
subject
|
str
|
Email subject line. |
required |
html_content
|
str | None
|
HTML body (preferred). Used as HTML part. |
required |
text_content
|
str | None
|
Plain-text body (fallback for HTML-disabled clients). If None and html_content is provided, a generic fallback is used. |
required |
timeout
|
int
|
SMTP connection timeout in seconds. |
15
|
Returns:
| Type | Description |
|---|---|
bool
|
True on success. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If aiosmtplib is not installed. |
SMTPException
|
On SMTP delivery failure. |
Source code in src/codex_platform/notifications/clients/smtp.py
ArqNotificationAdapter
Bases: NotificationAdapter
Notification adapter that enqueues tasks into an ARQ/Redis queue.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pool
|
ArqRedis
|
|
required |
Raises on infrastructure failures (Redis unavailable, serialization errors).
Source code in src/codex_platform/notifications/delivery/arq.py
Functions
enqueue(task_name, payload)
Sync enqueue — wraps async via asyncio. Use enqueue_async in async contexts.
Source code in src/codex_platform/notifications/delivery/arq.py
enqueue_async(task_name, payload)
async
Enqueue a notification task into the ARQ queue (async).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_name
|
str
|
ARQ worker function name (e.g. |
required |
payload
|
dict[str, Any]
|
Serialized |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
Job ID string, or None if ARQ returned no handle. |
Raises:
| Type | Description |
|---|---|
ConnectionError
|
Redis is unreachable. |
Exception
|
Any ARQ/Redis infrastructure failure. |
Source code in src/codex_platform/notifications/delivery/arq.py
DirectNotificationAdapter
Bases: NotificationAdapter
Adapter for synchronous/monolithic notification delivery.
Injects a pre-built list of channels (via ChannelRegistry) into
BaseDeliveryOrchestrator and runs the async pipeline synchronously.
Uses lazy imports to avoid circular dependencies.
Source code in src/codex_platform/notifications/delivery/direct.py
Functions
enqueue(_task_name, payload)
Deliver a notification synchronously via the orchestrator pipeline.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
_task_name
|
str
|
Unused — direct delivery runs in-process. |
required |
payload
|
dict[str, Any]
|
Serialized |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
|
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If called from within a running event loop. |
Exception
|
Channel infrastructure failures propagate upward. |
Source code in src/codex_platform/notifications/delivery/direct.py
NotificationAdapter
Bases: Protocol
Contract for notification delivery transport.
Allows the same business logic to work with ARQ, Celery, Direct calls, or Django's built-in mail system.
Implementations MUST
- Raise exceptions on infrastructure failures (network, broker, DB).
- Return a job/task ID (str) when the backend provides one.
- Return None for fire-and-forget transports with no tracking ID.
Source code in src/codex_platform/notifications/delivery/base.py
Functions
enqueue(task_name, payload)
Deliver or enqueue the notification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_name
|
str
|
Worker function name to execute. May be unused by adapters that deliver synchronously. |
required |
payload
|
dict[str, Any]
|
Serialized |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str | None
|
Job/task identifier for tracking. |
None |
str | None
|
When the transport is fire-and-forget. |
Raises:
| Type | Description |
|---|---|
Exception
|
Infrastructure errors MUST propagate — never swallow them. |
Source code in src/codex_platform/notifications/delivery/base.py
NotificationPayloadDTO
Bases: BaseDTO
Base notification payload — identification and routing only.
Do not use directly. Use TemplateNotificationDTO or RenderedNotificationDTO.
Source code in src/codex_platform/notifications/dto.py
NotificationRecipient
Bases: BaseDTO
Recipient info. PII fields auto-masked in repr via BaseDTO.
Source code in src/codex_platform/notifications/dto.py
RenderedNotificationDTO
Bases: NotificationPayloadDTO
Mode 2 — Pre-rendered HTML passed directly to the workers.
Use when Django (or another layer) renders the template and the workers only needs to deliver.
Source code in src/codex_platform/notifications/dto.py
TemplateNotificationDTO
Bases: NotificationPayloadDTO
Mode 1 — Worker renders the template itself (requires Jinja2).
Redis key where context_data is stored (JSON).
Allows updating data after enqueue (e.g. reschedule).
template_name: Relative template path (e.g. 'booking/bk_confirmation.html').
Source code in src/codex_platform/notifications/dto.py
ContentCacheAdapter
Bases: Protocol
Adapter for caching email/notification content (used by BaseEmailContentSelector).
Source code in src/codex_platform/notifications/interfaces.py
Functions
get_cached_value(key)
ContentProvider
Bases: Protocol
Provides translated template text by key.
Source code in src/codex_platform/notifications/interfaces.py
BaseDeliveryOrchestrator
Tries channels in order; stops on first success.
Channels are injected at construction time via Dependency Injection.
deliver() is a pure send operation with no side effects beyond delivery.
Source code in src/codex_platform/notifications/orchestrator.py
Functions
__init__(channels)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channels
|
list[DeliveryChannel]
|
Ordered list of delivery channels to try.
Use |
required |
deliver(payload)
async
Deliver a notification payload through available channels.
Tries each channel in order; stops on first success. If a channel raises, logs the exception and falls through to the next.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
NotificationPayloadDTO
|
|
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if at least one channel succeeded, False if all exhausted. |
Source code in src/codex_platform/notifications/orchestrator.py
DeliveryChannel
Bases: Protocol
Contract for a single delivery method.
Implementors: AsyncEmailClient, DjangoMailChannel, TelegramChannel, etc.
Source code in src/codex_platform/notifications/orchestrator.py
Functions
send(to, subject, html_content, text_content)
async
Attempt delivery. Return True on success, False on logical failure. Raise on infrastructure errors (so the orchestrator can log and try next channel).
Source code in src/codex_platform/notifications/orchestrator.py
ChannelRegistry
Registry for delivery channels. Channels register with a factory function that returns a channel or None. build_channels() creates only the channels whose config is available.
Source code in src/codex_platform/notifications/registry.py
Functions
register(name, factory)
Register a channel factory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Human-readable channel name (for logging). |
required |
factory
|
Callable[[Any], DeliveryChannel | None]
|
Callable that takes config and returns DeliveryChannel or None. Return None if the channel's config is missing/incomplete. |
required |
Source code in src/codex_platform/notifications/registry.py
build_channels(config)
Build the list of available channels from all registered factories.
Calls each factory with config. A channel is included only when the
factory returns a non-None instance that also reports is_available() == True.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Any
|
Application settings object passed verbatim to every factory. |
required |
Returns:
| Type | Description |
|---|---|
list[DeliveryChannel]
|
Ordered list of ready-to-use :class: |