Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion worker_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import re

DEFAULTS = dict(
DATABASE_URL="postgresql://admin:pechaAdmin@localhost:5434/pecha",
DATABASE_URL="postgresql://admin:pechaAdmin@localhost:5434/pecha-worker",
MONGO_CONNECTION_STRING="mongodb://admin:pechaAdmin@localhost:27017/pecha?authSource=admin",
MONGO_DATABASE_NAME="webuddhist",

Expand Down
27 changes: 26 additions & 1 deletion worker_api/notifications/services/backend_client.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import httpx

from uuid import UUID

from worker_api.config import get
from worker_api.notifications.schemas import RoutineNotificationTargetsResponse
from worker_api.notifications.schemas import NotificationContent, RoutineNotificationTargetsResponse


async def fetch_routine_notification_targets() -> RoutineNotificationTargetsResponse:
Expand All @@ -20,3 +22,26 @@ async def fetch_routine_notification_targets() -> RoutineNotificationTargetsResp
)
response.raise_for_status()
return RoutineNotificationTargetsResponse.model_validate(response.json())


async def fetch_plan_notification_content(
*,
user_id: UUID,
plan_id: UUID,
) -> NotificationContent:
backend_url = get("BACKEND_API_URL").rstrip("/")
if not backend_url:
raise RuntimeError("BACKEND_API_URL is not configured")

dispatch_token = get("NOTIFICATION_DISPATCH_SECRET_TOKEN")
if not dispatch_token:
raise RuntimeError("NOTIFICATION_DISPATCH_SECRET_TOKEN is not configured")

async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(
f"{backend_url}/internal/plan-notification-content",
params={"user_id": str(user_id), "plan_id": str(plan_id)},
headers={"X-Dispatch-Token": dispatch_token},
)
response.raise_for_status()
return NotificationContent.model_validate(response.json())
11 changes: 8 additions & 3 deletions worker_api/notifications/services/dispatch_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from worker_api.db.database import SessionLocal
from worker_api.notifications.repositories import reminder_repository
from worker_api.notifications.schemas import DispatchDueNotificationsResponse
from worker_api.notifications.services.notification_content_service import build_notification_content
from worker_api.notifications.services.notification_content_service import resolve_notification_content
from worker_api.notifications.services.push_service import (
_already_dispatched,
_mark_dispatched,
Expand Down Expand Up @@ -36,9 +36,14 @@ async def dispatch_due_notifications_service() -> DispatchDueNotificationsRespon
skipped += 1
continue

title, body = build_notification_content(reminder)
content = await resolve_notification_content(reminder)
try:
await send_push_notification(reminder, title, body)
await send_push_notification(
reminder,
content.title,
content.body,
content.image_url,
)
reminder_repository.mark_sent(db, reminder)
reminder_repository.create_reminder(
db,
Expand Down
23 changes: 23 additions & 0 deletions worker_api/notifications/services/notification_content_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import logging

from worker_api.config import get
from worker_api.notifications.models.reminder_models import UpcomingReminder
from worker_api.notifications.schemas import NotificationContent

logger = logging.getLogger(__name__)


def build_notification_content(reminder: UpcomingReminder) -> tuple[str, str]:
Expand All @@ -15,3 +20,21 @@ def build_notification_content(reminder: UpcomingReminder) -> tuple[str, str]:
body = f"Day {routine['current_day_number']}: time for your practice."

return title, body


async def resolve_notification_content(reminder: UpcomingReminder) -> NotificationContent:
from worker_api.notifications.services.backend_client import fetch_plan_notification_content

try:
return await fetch_plan_notification_content(
user_id=reminder.user_id,
plan_id=reminder.plan_id,
)
except Exception:
logger.exception(
"Failed to fetch plan notification content from backend for user %s plan %s",
reminder.user_id,
reminder.plan_id,
)
title, body = build_notification_content(reminder)
return NotificationContent(title=title, body=body, image_url=None)
10 changes: 8 additions & 2 deletions worker_api/notifications/services/push_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from worker_api.config import get, get_bool, get_int
from worker_api.notifications.enums import PushPlatform
from worker_api.notifications.models.reminder_models import UpcomingReminder
from worker_api.notifications.services.notification_content_service import build_notification_content
from worker_api.notifications.services.push.config_loader import is_push_configured
from worker_api.notifications.services.push.fcm_client import (
build_routine_notification_data,
Expand Down Expand Up @@ -49,7 +48,12 @@ def _mark_dispatched(reminder_id: UUID) -> None:
)


async def send_push_notification(reminder: UpcomingReminder, title: str, body: str) -> None:
async def send_push_notification(
reminder: UpcomingReminder,
title: str,
body: str,
image_url: str | None = None,
) -> None:
if not is_push_configured(reminder.platform):
logger.warning(
"Push not configured for platform %s; skipping send for reminder %s",
Expand All @@ -63,11 +67,13 @@ async def send_push_notification(reminder: UpcomingReminder, title: str, body: s
device_token=reminder.device_token,
title=title,
body=body,
image_url=image_url,
data=build_routine_notification_data(
session_type="PLAN",
source_id=reminder.plan_id,
title=title,
body=body,
image_url=image_url,
),
)
return
Expand Down
Loading