mirror of
https://github.com/sstent/FitTrack_GarminSync.git
synced 2026-01-30 02:51:55 +00:00
167 lines
7.1 KiB
Python
167 lines
7.1 KiB
Python
import logging
|
|
from pathlib import Path
|
|
from typing import Optional, List
|
|
import httpx
|
|
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
|
|
|
|
from ..schemas import GarminCredentials, Token, User, WorkoutPlan
|
|
from ..config import settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Define a retry strategy for CentralDB calls
|
|
CENTRAL_DB_RETRY_STRATEGY = retry(
|
|
stop=stop_after_attempt(5),
|
|
wait=wait_exponential(multiplier=1, min=2, max=10),
|
|
retry=retry_if_exception_type(httpx.RequestError), # Retry on network errors
|
|
reraise=True
|
|
)
|
|
|
|
class CentralDBService:
|
|
def __init__(self, base_url: str):
|
|
self.base_url = base_url
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def get_user_by_email(self, email: str) -> Optional[User]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get(f"{self.base_url}/users")
|
|
response.raise_for_status()
|
|
users = response.json()
|
|
for user_data in users:
|
|
if user_data["email"] == email:
|
|
return User(**user_data)
|
|
return None
|
|
except Exception as e:
|
|
logger.error(f"Error fetching user from CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def get_user(self, user_id: int) -> Optional[User]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get(f"{self.base_url}/users/{user_id}")
|
|
response.raise_for_status()
|
|
return User(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error fetching user from CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def create_user(self, user_create: dict) -> Optional[User]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.post(f"{self.base_url}/users", json=user_create)
|
|
response.raise_for_status()
|
|
return User(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error creating user in CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def get_token(self, user_id: int) -> Optional[Token]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get(f"{self.base_url}/tokens/{user_id}")
|
|
response.raise_for_status()
|
|
return Token(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error fetching token from CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def create_token(self, token_create: dict) -> Optional[Token]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.post(f"{self.base_url}/tokens/", json=token_create)
|
|
response.raise_for_status()
|
|
return Token(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error creating token in CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def update_token(self, user_id: int, token_update: dict) -> Optional[Token]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.put(f"{self.base_url}/tokens/{user_id}", json=token_update)
|
|
response.raise_for_status()
|
|
return Token(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error updating token in CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def get_workout_by_id(self, workout_id: int) -> Optional[WorkoutPlan]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get(f"{self.base_url}/workout_plans/{workout_id}")
|
|
response.raise_for_status()
|
|
return WorkoutPlan(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error fetching workout from CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def upload_activity_file(self, activity_id: str, file_path: Path) -> bool:
|
|
"""Uploads activity file content to CentralDB."""
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
with open(file_path, "rb") as f:
|
|
files = {"file": (file_path.name, f, "application/fit")} # Changed content type
|
|
user_id = 1 # Assuming single user for now
|
|
response = await client.post(
|
|
f"{self.base_url}/activities/{user_id}", # user_id as path parameter
|
|
files=files,
|
|
)
|
|
response.raise_for_status()
|
|
logger.info(f"Successfully uploaded activity {activity_id} to CentralDB.")
|
|
return True
|
|
except Exception as e:
|
|
logger.error(f"Error uploading activity {activity_id} to CentralDB: {e}", exc_info=True)
|
|
return False
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def save_health_metric(self, health_metric_data: dict) -> Optional[dict]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.post(f"{self.base_url}/health_metrics", json=health_metric_data)
|
|
response.raise_for_status()
|
|
return response.json()
|
|
except Exception as e:
|
|
logger.error(f"Error saving health metric to CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def get_garmin_credentials(self, user_id: int) -> Optional[GarminCredentials]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get(f"{self.base_url}/garmin_credentials/{user_id}")
|
|
response.raise_for_status()
|
|
return GarminCredentials(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error fetching Garmin credentials from CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def create_garmin_credentials(self, user_id: int, credentials_data: dict) -> Optional[GarminCredentials]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.post(f"{self.base_url}/garmin_credentials/{user_id}", json=credentials_data)
|
|
response.raise_for_status()
|
|
return GarminCredentials(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error creating Garmin credentials in CentralDB: {e}")
|
|
return None
|
|
|
|
@CENTRAL_DB_RETRY_STRATEGY
|
|
async def update_garmin_credentials(self, user_id: int, credentials_data: dict) -> Optional[GarminCredentials]:
|
|
try:
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.put(f"{self.base_url}/garmin_credentials/{user_id}", json=credentials_data)
|
|
response.raise_for_status()
|
|
return GarminCredentials(**response.json())
|
|
except Exception as e:
|
|
logger.error(f"Error updating Garmin credentials in CentralDB: {e}")
|
|
return None
|