mirror of
https://github.com/sstent/AICyclingCoach.git
synced 2026-02-08 07:22:19 +00:00
sync
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy import select, desc
|
||||
from app.services.garmin import GarminService, GarminAPIError, GarminAuthError
|
||||
from app.models.workout import Workout
|
||||
from app.models.garmin_sync_log import GarminSyncLog
|
||||
from app.models.garmin_sync_log import GarminSyncLog
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
import asyncio
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -34,11 +36,27 @@ class WorkoutSyncService:
|
||||
|
||||
synced_count = 0
|
||||
for activity in activities:
|
||||
if await self.activity_exists(activity['activityId']):
|
||||
activity_id = activity['activityId']
|
||||
if await self.activity_exists(activity_id):
|
||||
continue
|
||||
|
||||
# Get full activity details with retry logic
|
||||
max_retries = 3
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
details = await self.garmin_service.get_activity_details(activity_id)
|
||||
break
|
||||
except (GarminAPIError, GarminAuthError) as e:
|
||||
if attempt == max_retries - 1:
|
||||
raise
|
||||
await asyncio.sleep(2 ** attempt)
|
||||
logger.warning(f"Retrying activity details fetch for {activity_id}, attempt {attempt + 1}")
|
||||
|
||||
# Merge basic activity data with detailed metrics
|
||||
full_activity = {**activity, **details}
|
||||
|
||||
# Parse and create workout
|
||||
workout_data = await self.parse_activity_data(activity)
|
||||
workout_data = await self.parse_activity_data(full_activity)
|
||||
workout = Workout(**workout_data)
|
||||
self.db.add(workout)
|
||||
synced_count += 1
|
||||
@@ -52,8 +70,14 @@ class WorkoutSyncService:
|
||||
logger.info(f"Successfully synced {synced_count} activities")
|
||||
return synced_count
|
||||
|
||||
except GarminAuthError as e:
|
||||
sync_log.status = "auth_error"
|
||||
sync_log.error_message = str(e)
|
||||
await self.db.commit()
|
||||
logger.error(f"Garmin authentication failed: {str(e)}")
|
||||
raise
|
||||
except GarminAPIError as e:
|
||||
sync_log.status = "error"
|
||||
sync_log.status = "api_error"
|
||||
sync_log.error_message = str(e)
|
||||
await self.db.commit()
|
||||
logger.error(f"Garmin API error during sync: {str(e)}")
|
||||
@@ -65,6 +89,15 @@ class WorkoutSyncService:
|
||||
logger.error(f"Unexpected error during sync: {str(e)}")
|
||||
raise
|
||||
|
||||
async def get_latest_sync_status(self):
|
||||
"""Get the most recent sync log entry"""
|
||||
result = await self.db.execute(
|
||||
select(GarminSyncLog)
|
||||
.order_by(desc(GarminSyncLog.created_at))
|
||||
.limit(1)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
async def activity_exists(self, garmin_activity_id: str) -> bool:
|
||||
"""Check if activity already exists in database."""
|
||||
result = await self.db.execute(
|
||||
|
||||
Reference in New Issue
Block a user