Notifications
Active contributors: Sergio Castaño Arteaga, Cintia Sánchez García, Sako Mammadov
Purpose
The notifications feature sends transactional email messages to users for platform events such as event RSVPs, event cancellations, team invitations, payment confirmations, and onboarding. Emails are composed from typed Askama templates and delivered asynchronously via SMTP using the Lettre crate.
Directory layout
ocg-server/src/
├── services/notifications.rs # PgNotificationsManager, LettreEmailSender, delivery worker
├── services/notifications/
│ ├── enqueue.rs # enqueue_* helper functions for each notification type
│ ├── payloads.rs # typed payload structs for each notification
│ └── tests.rs # integration tests
├── templates/notifications.rs # Askama template structs (one per email type)
└── templates/notifications/ # .html Askama template files
Key abstractions
| Abstraction | File | Description |
|---|---|---|
PgNotificationsManager |
ocg-server/src/services/notifications.rs |
Queues notifications to PostgreSQL and runs the delivery worker |
DynNotificationsManager |
ocg-server/src/services/notifications.rs |
Arc<dyn NotificationsManager> — used by handlers and other services |
LettreEmailSender |
ocg-server/src/services/notifications.rs |
Wraps lettre::AsyncSmtpTransport for SMTP delivery |
DynEmailSender |
ocg-server/src/services/notifications.rs |
Arc<dyn EmailSender> — allows mock replacement in tests |
DBNotifications |
ocg-server/src/db/notifications.rs |
Trait: enqueue_notification, claim_notifications, mark_delivered, requeue_failed |
How it works
sequenceDiagram
participant Handler
participant NotificationsManager
participant DB as PostgreSQL (notifications queue)
participant DeliveryWorker
participant SMTP
Handler->>NotificationsManager: enqueue_event_published(payload)
NotificationsManager->>DB: INSERT INTO notifications (kind, payload, status=pending)
loop every poll interval
DeliveryWorker->>DB: claim up to N pending notifications
DB-->>DeliveryWorker: claimed rows
loop for each notification
DeliveryWorker->>DeliveryWorker: render Askama template
DeliveryWorker->>SMTP: send email (up to 3 attempts)
alt success
DeliveryWorker->>DB: mark_delivered
else retryable failure
DeliveryWorker->>DB: requeue with exponential backoff
else max claims exceeded
DeliveryWorker->>DB: mark_failed (terminal)
end
end
end
Delivery guarantees
- Notifications are written to the database before being sent, providing at-least-once delivery semantics.
- Failed deliveries are retried with exponential backoff: initial delay 1 minute, maximum 30 minutes.
- After
DELIVERY_MAX_CLAIMS(10) attempts, a notification is marked terminal and will not be retried. - A processing timeout of 15 minutes detects crashed worker instances and reclaims stuck notifications.
Email templates
Each notification type has a corresponding Askama template struct in ocg-server/src/templates/notifications.rs. Templates are compiled at build time and render both HTML and plain-text parts.
| Template | Trigger |
|---|---|
EventPublished |
Organizer publishes an event |
EventCanceled |
Organizer cancels an event |
EventSeriesCanceled |
Organizer cancels an event series |
EventRescheduled |
Event time/location is changed |
EventReminder |
Pre-event reminder to registered attendees |
EventWelcome |
RSVP confirmation to new attendee |
EventInvitation |
Organizer sends a personal invitation |
EventSeriesPublished |
Event series is published |
EventWaitlistJoined |
User is placed on the waitlist |
EventWaitlistLeft |
User leaves the waitlist |
EventWaitlistPromoted |
Waitlisted user is promoted to confirmed |
EventCustom |
Ad-hoc message to event attendees |
EventRefundRequested |
Attendee requests a refund (sent to organizer) |
EventRefundApproved |
Organizer approves a refund |
EventRefundRejected |
Organizer rejects a refund |
GroupWelcome |
User joins a group |
GroupCustom |
Ad-hoc message to group members |
GroupTeamInvitation |
User is invited to a group team |
AllianceTeamInvitation |
User is invited to an alliance team |
EmailVerification |
New user email verification |
SiteOnboarding |
Post-registration onboarding email |
CoffeeMeetSuggestion |
Coffee meet suggestion for networking |
MockInterviewMatched |
Mock interview match notification |
IntentionalDatingIntroduction |
Intentional dating introduction |
CfsSubmissionUpdated |
CFS/talk proposal status update |
SessionProposalCoSpeakerInvitation |
Co-speaker invitation for a session proposal |
SpeakerWelcome |
New speaker welcome |
SpeakerSeriesWelcome |
Speaker series welcome |
Configuration
SMTP settings are in the email section of the config:
| Config key | Env var | Description |
|---|---|---|
email.smtp_host |
OCG_EMAIL__SMTP_HOST |
SMTP server hostname |
email.smtp_port |
OCG_EMAIL__SMTP_PORT |
Port (defaults to 465 for SMTPS) |
email.smtp_username |
OCG_EMAIL__SMTP_USERNAME |
SMTP auth username |
email.smtp_password |
OCG_EMAIL__SMTP_PASSWORD |
SMTP auth password |
email.from_name |
OCG_EMAIL__FROM_NAME |
Display name in From header |
email.from_address |
OCG_EMAIL__FROM_ADDRESS |
From email address |
Integration points
- Events — most notification types are enqueued by event handlers or the payments manager.
- Payments — refund request/approval/rejection emails.
- Auth —
EmailVerificationandSiteOnboardingtemplates. - Groups and alliances —
GroupWelcome,GroupTeamInvitation,AllianceTeamInvitation.
Entry points for modification
- Add a new notification type: create an Askama template struct in
ocg-server/src/templates/notifications.rs, add an HTML template file, add a payload struct inocg-server/src/services/notifications/payloads.rs, and add anenqueue_*helper inocg-server/src/services/notifications/enqueue.rs. - Change retry behavior: update
DELIVERY_MAX_CLAIMS,DELIVERY_REQUEUE_BASE_DELAY, orDELIVERY_REQUEUE_MAX_DELAYconstants inocg-server/src/services/notifications.rs. - Replace the SMTP provider: implement
EmailSenderfor the new transport and updatesetup_notifications_managerinocg-server/src/main.rs.