Fixed Garmin sync progress bar granularity, timeout issue, and lookback days input, plus redesigned the sleep timeline with taller bars and yellow Awake colour.
Build and push images / validate (push) Successful in 3s
Build and push images / build-backend (push) Successful in 48s
Build and push images / build-worker (push) Successful in 44s
Build and push images / build-frontend (push) Successful in 28s

This commit is contained in:
2026-06-07 18:15:07 +01:00
parent bf1920eb9d
commit 492418586a
5 changed files with 120 additions and 59 deletions
+16 -3
View File
@@ -72,7 +72,8 @@ def authenticate_garmin(email: str, password_enc: str, token_store: Optional[str
# ── Activity sync ─────────────────────────────────────────────────────────────
def sync_activities(garmin, user_id: int, since: Optional[datetime],
db, file_store_path: str, lookback_days: int = 30) -> int:
db, file_store_path: str, lookback_days: int = 30,
status_callback=None) -> int:
"""
List activities from Garmin Connect, skip any already in the DB, download
FIT ZIPs for new ones, and queue them for processing.
@@ -108,6 +109,10 @@ def sync_activities(garmin, user_id: int, since: Optional[datetime],
logger.error("Failed to list Garmin activities: %s", exc)
return 0
total = len(activities)
if status_callback and total:
status_callback(f"Syncing activities: 0/{total} queued")
queued = 0
for act in activities:
garmin_id = str(act.get("activityId", "")).strip()
@@ -173,6 +178,9 @@ def sync_activities(garmin, user_id: int, since: Optional[datetime],
process_activity_file.delay(str(dest), user_id, "fit", garmin_id)
queued += 1
if status_callback and (queued % 5 == 0 or queued == total):
status_callback(f"Syncing activities: {queued}/{total} queued")
# Brief pause to avoid hammering the Garmin API
time.sleep(0.5)
@@ -182,7 +190,7 @@ def sync_activities(garmin, user_id: int, since: Optional[datetime],
# ── Wellness sync ─────────────────────────────────────────────────────────────
def sync_wellness(garmin, user_id: int, since: Optional[datetime], db,
lookback_days: int = 90) -> int:
lookback_days: int = 90, status_callback=None) -> int:
"""
Fetch daily stats / sleep / HRV from the Garmin Connect JSON API for each
day in the window and upsert into health_metrics.
@@ -209,8 +217,13 @@ def sync_wellness(garmin, user_id: int, since: Optional[datetime], db,
import time as _time
import json as _json
for i in range(max(days, 1)):
total_days = max(days, 1)
if status_callback:
status_callback(f"Syncing wellness: 0/{total_days} days")
for i in range(total_days):
day = start_date + timedelta(days=i)
if status_callback and (i % 5 == 0 or i == total_days - 1):
status_callback(f"Syncing wellness: {i + 1}/{total_days} days")
day_str = day.isoformat()
stats = _safe(garmin.get_stats, day_str)
+8 -4
View File
@@ -511,24 +511,28 @@ def sync_garmin_connect_user(user_id: int):
wellness_days = 0
errors = []
if sync_acts:
cfg.last_sync_status = "Syncing activities..."
def _set_status(text):
cfg.last_sync_status = text
db.commit()
if sync_acts:
_set_status("Syncing activities...")
try:
activities_queued = sync_activities(
garmin, user_id, last_sync_at, db, settings.file_store_path,
lookback_days=lookback,
status_callback=_set_status,
)
except Exception as exc:
errors.append(f"activities: {exc}")
if sync_well:
cfg.last_sync_status = "Syncing wellness data..."
db.commit()
_set_status("Syncing wellness...")
try:
wellness_days = sync_wellness(
garmin, user_id, last_sync_at, db,
lookback_days=lookback,
status_callback=_set_status,
)
except Exception as exc:
errors.append(f"wellness: {exc}")