mirror of
https://github.com/sstent/FitTrack_GarminSync.git
synced 2026-01-25 08:35:23 +00:00
97 lines
3.3 KiB
Python
97 lines
3.3 KiB
Python
import logging
|
|
import uuid
|
|
from typing import Any, Dict, Optional
|
|
|
|
from tenacity import (
|
|
retry,
|
|
retry_if_exception_type,
|
|
stop_after_attempt,
|
|
wait_exponential,
|
|
)
|
|
|
|
from ..services.garmin_client_service import GarminClientService
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Define a common retry strategy for Garmin API calls
|
|
GARMIN_RETRY_STRATEGY = retry(
|
|
stop=stop_after_attempt(5),
|
|
wait=wait_exponential(multiplier=1, min=4, max=10),
|
|
retry=retry_if_exception_type(Exception), # Broad exception for now, refine later
|
|
reraise=True,
|
|
)
|
|
|
|
|
|
class GarminWorkoutService:
|
|
def __init__(self, garmin_client_service: GarminClientService):
|
|
self.garmin_client_service = garmin_client_service
|
|
|
|
@GARMIN_RETRY_STRATEGY
|
|
async def upload_workout(self, workout_id: uuid.UUID) -> Optional[Dict[str, Any]]:
|
|
try:
|
|
# Get workout from CentralDB
|
|
from ..config import settings
|
|
from .central_db_service import CentralDBService
|
|
|
|
central_db = CentralDBService(base_url=settings.CENTRAL_DB_URL)
|
|
workout = await central_db.get_workout_by_id(
|
|
workout_id
|
|
) # Assuming this method exists
|
|
|
|
if not workout:
|
|
logger.error(f"Workout with ID {workout_id} not found in CentralDB.")
|
|
return None
|
|
|
|
garmin_client = self.garmin_client_service.get_client()
|
|
if not garmin_client:
|
|
raise Exception("Garmin client not authenticated.")
|
|
|
|
logger.info(
|
|
f"Simulating upload of workout {workout.name} (ID: {workout_id}) "
|
|
"to Garmin Connect."
|
|
)
|
|
garmin_workout_id = f"GARMIN_WORKOUT_{workout_id}" # Mock ID
|
|
|
|
# Here we would update the workout in CentralDB with the garmin_workout_id
|
|
# await central_db.update_workout(
|
|
# workout_id, {"garmin_workout_id": garmin_workout_id, "upload_status": "completed"}
|
|
# )
|
|
|
|
logger.info(
|
|
f"Successfully uploaded workout {workout.name} to Garmin Connect "
|
|
f"with ID {garmin_workout_id}."
|
|
)
|
|
|
|
# We need to add garmin_workout_id to the workout dictionary before returning
|
|
workout_dict = workout.dict()
|
|
workout_dict["garmin_workout_id"] = garmin_workout_id
|
|
|
|
return workout_dict
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error uploading workout {workout_id}: {e}", exc_info=True)
|
|
# We could update the workout in CentralDB to set the status to "failed"
|
|
# await central_db.update_workout(workout_id, {"upload_status": "failed"})
|
|
return None
|
|
|
|
async def upload_workout_in_background(
|
|
self,
|
|
user_id: int,
|
|
current_sync_job_manager,
|
|
workout_id: uuid.UUID,
|
|
):
|
|
try:
|
|
|
|
uploaded_workout = await self.upload_workout(workout_id)
|
|
|
|
if uploaded_workout:
|
|
await current_sync_job_manager.complete_sync()
|
|
else:
|
|
await current_sync_job_manager.fail_sync(
|
|
error_message=f"Failed to upload workout {workout_id}"
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error during workout upload: {e}", exc_info=True)
|
|
await current_sync_job_manager.fail_sync(error_message=str(e))
|