Skip to content

Commit

Permalink
Merge pull request #93 from voynow/91-email-on-new-activity
Browse files Browse the repository at this point in the history
91 email on new activity
  • Loading branch information
voynow authored Oct 10, 2024
2 parents bef3c95 + 2a92f21 commit 04876d9
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 65 deletions.
14 changes: 9 additions & 5 deletions src/lambda_function.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import os
import traceback
import uuid

from src import auth_manager, frontend_router, update_pipeline, webhook_router
Expand All @@ -9,7 +10,7 @@
logger.setLevel(logging.INFO)


def strategy_router(event: dict) -> dict:
def strategy_router(event: dict, invocation_id: str) -> dict:

# Will fail on bad authenticate_with_code
if event.get("email") and event.get("code"):
Expand Down Expand Up @@ -44,10 +45,10 @@ def strategy_router(event: dict) -> dict:
event.get("resources")
and event.get("resources")[0] == os.environ["NIGHTLY_EMAIL_TRIGGER_ARN"]
):
return update_pipeline.nightly_trigger_orchestrator()
return update_pipeline.nightly_trigger_orchestrator(invocation_id)

elif event.get("trigger_test_key") == os.environ["TRIGGER_TEST_KEY"]:
return update_pipeline.integration_test_executor()
return update_pipeline.integration_test_executor(invocation_id)
else:
return {"success": False, "error": f"Unknown event type: {event}"}

Expand All @@ -65,9 +66,12 @@ def lambda_handler(event, context):
logger.info(f"{invocation_id=} | {event=} | {context=}")

try:
response = strategy_router(event)
response = strategy_router(event, invocation_id)
except Exception as e:
response = {"success": False, "error": str(e)}
response = {
"success": False,
"error": f"{invocation_id=} | Error in lambda_handler: {str(e)}\nTraceback: {traceback.format_exc()}",
}

# Ensure response is a dictionary
if type(response) is not dict:
Expand Down
2 changes: 1 addition & 1 deletion src/supabase_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ def has_user_updated_today(athlete_id: int) -> bool:
return False

# "Has this user posted an activity in the last 23 hours and 30 minutes?"
time_diff = datetime.now(timezone.utc) - datetime.fromisoformat(
time_diff = datetime.datetime.now(timezone.utc) - datetime.datetime.fromisoformat(
response.data[0]["created_at"]
)
return time_diff < timedelta(hours=23, minutes=30)
4 changes: 0 additions & 4 deletions src/types/update_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,3 @@
class ExeType(StrEnum):
NEW_WEEK = "new_week"
MID_WEEK = "mid_week"


class TrainingWeekUpdateError(Exception):
pass
29 changes: 22 additions & 7 deletions src/update_pipeline.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import logging
import os
import traceback
from typing import Callable, Dict

from openai import APIResponse
Expand All @@ -13,7 +14,7 @@
)
from src.auth_manager import get_strava_client
from src.constants import COACH_ROLE
from src.email_manager import send_email, training_week_to_html
from src.email_manager import send_alert_email, send_email, training_week_to_html
from src.mid_week_update import generate_mid_week_update
from src.new_training_week import generate_new_training_week
from src.supabase_client import (
Expand All @@ -25,7 +26,7 @@
upsert_training_week,
)
from src.types.training_week import TrainingWeek
from src.types.update_pipeline import ExeType, TrainingWeekUpdateError
from src.types.update_pipeline import ExeType
from src.types.user_row import UserRow
from src.utils import datetime_now_est

Expand Down Expand Up @@ -107,8 +108,13 @@ def webhook_executor(user: UserRow) -> dict:
return {"success": True}


def training_week_update_executor(user: UserRow, exetype: ExeType) -> dict:
"""Decides between generating a new week or updating based on the day."""
def training_week_update_executor(
user: UserRow, exetype: ExeType, invocation_id: str
) -> dict:
"""
Decides between generating a new week or updating based on the day.
Captures and logs full tracebacks for errors.
"""
try:
if exetype == ExeType.NEW_WEEK:
training_week_update_pipeline(
Expand All @@ -123,10 +129,19 @@ def training_week_update_executor(user: UserRow, exetype: ExeType) -> dict:
email_subject="TrackFlow Update Inbound! 🏃‍♂️🎯",
)
except Exception as e:
raise TrainingWeekUpdateError(f"Error processing user {user.athlete_id}: {e}")
error_msg = f"{invocation_id=} | Error processing user {user.athlete_id} | {str(e)}\nTraceback: {traceback.format_exc()}"
logger.error(error_msg)
send_alert_email(
subject="TrackFlow Alert: Error in lambda_handler",
text_content=error_msg,
)

return {"success": False, "error": str(e)}

return {"success": True}


def integration_test_executor() -> dict:
def integration_test_executor(invocation_id: str) -> dict:
"""
Run a full update pipeline for Jamies account
"""
Expand All @@ -139,7 +154,7 @@ def integration_test_executor() -> dict:
return {"success": True}


def nightly_trigger_orchestrator() -> dict:
def nightly_trigger_orchestrator(invocation_id: str) -> dict:
"""
Evenings excluding Sunday: Send update to users who have not yet triggered an update today
Sunday evening: Send new training week to all active users
Expand Down
7 changes: 5 additions & 2 deletions src/webhook_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ def handle_activity_create(user, event):
if activity.sport_type == "Run":
return training_week_update_executor(user, ExeType.MID_WEEK)

return {"success": False, "error": "Unsupported activity type"}
return {
"success": False,
"error": f"Unsupported activity type: {activity.sport_type}",
}


def handle_request(event: dict) -> dict:
Expand Down Expand Up @@ -43,4 +46,4 @@ def handle_request(event: dict) -> dict:
"message": f"Activity {event.get('object_id')} {aspect_type}d",
}

return {"success": False, "error": "Unknown event type"}
return {"success": False, "error": f"Unknown event type: {event_type}"}
39 changes: 0 additions & 39 deletions test.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -213,45 +213,6 @@
"# response.json()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"No rates present in response headers\n"
]
}
],
"source": [
"from src.supabase_client import get_user\n",
"from src.auth_manager import get_strava_client\n",
"\n",
"user = get_user(104454087)\n",
"strava_client = get_strava_client(user.athlete_id)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
11 changes: 6 additions & 5 deletions tests/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,28 @@
from freezegun import freeze_time

from src.auth_manager import get_strava_client
from src.lambda_function import daily_executor
from src.supabase_client import get_user
from src.types.update_pipeline import ExeType
from src.types.user_row import UserRow
from src.update_pipeline import training_week_update_executor


def daily_executor_wrapper(date_str: str):
def daily_executor_wrapper(date_str: str, exetype: ExeType):

day = datetime.datetime.strptime(date_str, "%Y-%m-%d").strftime("%A")
print(f"E2E execution at {date_str} ({day})")

@freeze_time(f"{date_str} 23:59:59")
def test_daily_executor(user: UserRow):
daily_executor(user)
training_week_update_executor(user, exetype)

user = get_user(os.environ["JAMIES_ATHLETE_ID"])
get_strava_client(user.athlete_id)
return test_daily_executor(user)


# New training week
daily_executor_wrapper("2024-09-08")
daily_executor_wrapper("2024-09-08", ExeType.NEW_WEEK)

# Update training week
daily_executor_wrapper("2024-09-09")
daily_executor_wrapper("2024-09-09", ExeType.MID_WEEK)
4 changes: 2 additions & 2 deletions web/src/app/strava_webhook/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export async function POST(request: NextRequest) {
const errorData = await response.json();
console.log(`Error response from signup API: ${JSON.stringify(errorData)}`);
}
} catch (error) {
console.error(`Error occurred while processing POST request: ${error}`);
} catch (error: any) {
console.error(`Error occurred while processing POST request: ${error.message}`);
}
})();

Expand Down

0 comments on commit 04876d9

Please sign in to comment.