fix: add retry logic for garmin 429 rate limiting
This commit is contained in:
@@ -1,118 +1,125 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: garmin-sync-script
|
||||
namespace: garmin
|
||||
data:
|
||||
sync.py: |
|
||||
import os
|
||||
import json
|
||||
from datetime import date, timedelta
|
||||
import psycopg2
|
||||
from garminconnect import Garmin
|
||||
import os
|
||||
import time
|
||||
from datetime import date, timedelta
|
||||
import psycopg2
|
||||
from garminconnect import Garmin
|
||||
|
||||
email = os.environ["GARMIN_EMAIL"]
|
||||
password = os.environ["GARMIN_PASSWORD"]
|
||||
db_url = os.environ["DATABASE_URL"]
|
||||
email = os.environ["GARMIN_EMAIL"]
|
||||
password = os.environ["GARMIN_PASSWORD"]
|
||||
db_url = os.environ["DATABASE_URL"]
|
||||
|
||||
client = Garmin(email, password)
|
||||
client.login()
|
||||
# Retry-Login bei 429
|
||||
client = Garmin(email, password)
|
||||
for attempt in range(5):
|
||||
try:
|
||||
client.login()
|
||||
print(f"Login erfolgreich (Versuch {attempt + 1})")
|
||||
break
|
||||
except Exception as e:
|
||||
if "429" in str(e):
|
||||
wait = 60 * (attempt + 1)
|
||||
print(f"Rate limited (429), warte {wait}s...")
|
||||
time.sleep(wait)
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
raise Exception("Login nach 5 Versuchen fehlgeschlagen")
|
||||
|
||||
today = date.today()
|
||||
start = today - timedelta(days=365 * 3)
|
||||
today = date.today()
|
||||
start = today - timedelta(days=365 * 3)
|
||||
|
||||
activities = client.get_activities_by_date(
|
||||
start.isoformat(), today.isoformat()
|
||||
activities = client.get_activities_by_date(
|
||||
start.isoformat(), today.isoformat()
|
||||
)
|
||||
|
||||
conn = psycopg2.connect(db_url)
|
||||
cur = conn.cursor()
|
||||
|
||||
cur.execute("""
|
||||
CREATE TABLE IF NOT EXISTS activities (
|
||||
id BIGINT PRIMARY KEY,
|
||||
name TEXT,
|
||||
type TEXT,
|
||||
start_time TIMESTAMP,
|
||||
duration_seconds FLOAT,
|
||||
distance_meters FLOAT,
|
||||
avg_hr INTEGER,
|
||||
max_hr INTEGER,
|
||||
avg_pace FLOAT,
|
||||
vo2max FLOAT,
|
||||
calories FLOAT,
|
||||
elevation_gain FLOAT,
|
||||
steps INTEGER,
|
||||
cadence FLOAT,
|
||||
hr_zone_1 FLOAT,
|
||||
hr_zone_2 FLOAT,
|
||||
hr_zone_3 FLOAT,
|
||||
hr_zone_4 FLOAT,
|
||||
hr_zone_5 FLOAT
|
||||
)
|
||||
""")
|
||||
|
||||
conn = psycopg2.connect(db_url)
|
||||
cur = conn.cursor()
|
||||
cur.execute("""
|
||||
ALTER TABLE activities
|
||||
ADD COLUMN IF NOT EXISTS max_hr INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS vo2max FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS calories FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS elevation_gain FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS steps INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS cadence FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_1 FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_2 FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_3 FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_4 FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_5 FLOAT
|
||||
""")
|
||||
|
||||
for a in activities:
|
||||
cur.execute("""
|
||||
CREATE TABLE IF NOT EXISTS activities (
|
||||
id BIGINT PRIMARY KEY,
|
||||
name TEXT,
|
||||
type TEXT,
|
||||
start_time TIMESTAMP,
|
||||
duration_seconds FLOAT,
|
||||
distance_meters FLOAT,
|
||||
avg_hr INTEGER,
|
||||
max_hr INTEGER,
|
||||
avg_pace FLOAT,
|
||||
vo2max FLOAT,
|
||||
calories FLOAT,
|
||||
elevation_gain FLOAT,
|
||||
steps INTEGER,
|
||||
cadence FLOAT,
|
||||
hr_zone_1 FLOAT,
|
||||
hr_zone_2 FLOAT,
|
||||
hr_zone_3 FLOAT,
|
||||
hr_zone_4 FLOAT,
|
||||
hr_zone_5 FLOAT
|
||||
)
|
||||
""")
|
||||
INSERT INTO activities
|
||||
(id, name, type, start_time, duration_seconds, distance_meters,
|
||||
avg_hr, max_hr, avg_pace, vo2max, calories, elevation_gain,
|
||||
steps, cadence, hr_zone_1, hr_zone_2, hr_zone_3, hr_zone_4, hr_zone_5)
|
||||
VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
duration_seconds = EXCLUDED.duration_seconds,
|
||||
distance_meters = EXCLUDED.distance_meters,
|
||||
avg_hr = EXCLUDED.avg_hr,
|
||||
max_hr = EXCLUDED.max_hr,
|
||||
avg_pace = EXCLUDED.avg_pace,
|
||||
vo2max = EXCLUDED.vo2max,
|
||||
calories = EXCLUDED.calories,
|
||||
elevation_gain = EXCLUDED.elevation_gain,
|
||||
steps = EXCLUDED.steps,
|
||||
cadence = EXCLUDED.cadence,
|
||||
hr_zone_1 = EXCLUDED.hr_zone_1,
|
||||
hr_zone_2 = EXCLUDED.hr_zone_2,
|
||||
hr_zone_3 = EXCLUDED.hr_zone_3,
|
||||
hr_zone_4 = EXCLUDED.hr_zone_4,
|
||||
hr_zone_5 = EXCLUDED.hr_zone_5
|
||||
""", (
|
||||
a.get("activityId"),
|
||||
a.get("activityName"),
|
||||
a.get("activityType", {}).get("typeKey"),
|
||||
a.get("startTimeLocal"),
|
||||
a.get("duration"),
|
||||
a.get("distance"),
|
||||
a.get("averageHR"),
|
||||
a.get("maxHR"),
|
||||
a.get("averageSpeed"),
|
||||
a.get("vO2MaxValue"),
|
||||
a.get("calories"),
|
||||
a.get("elevationGain"),
|
||||
a.get("steps"),
|
||||
a.get("averageRunningCadenceInStepsPerMinute"),
|
||||
a.get("hrTimeInZone_1"),
|
||||
a.get("hrTimeInZone_2"),
|
||||
a.get("hrTimeInZone_3"),
|
||||
a.get("hrTimeInZone_4"),
|
||||
a.get("hrTimeInZone_5"),
|
||||
))
|
||||
|
||||
cur.execute("""
|
||||
ALTER TABLE activities
|
||||
ADD COLUMN IF NOT EXISTS max_hr INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS vo2max FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS calories FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS elevation_gain FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS steps INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS cadence FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_1 FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_2 FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_3 FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_4 FLOAT,
|
||||
ADD COLUMN IF NOT EXISTS hr_zone_5 FLOAT
|
||||
""")
|
||||
|
||||
for a in activities:
|
||||
cur.execute("""
|
||||
INSERT INTO activities
|
||||
(id, name, type, start_time, duration_seconds, distance_meters,
|
||||
avg_hr, max_hr, avg_pace, vo2max, calories, elevation_gain,
|
||||
steps, cadence, hr_zone_1, hr_zone_2, hr_zone_3, hr_zone_4, hr_zone_5)
|
||||
VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
|
||||
ON CONFLICT (id) DO UPDATE SET
|
||||
duration_seconds = EXCLUDED.duration_seconds,
|
||||
distance_meters = EXCLUDED.distance_meters,
|
||||
avg_hr = EXCLUDED.avg_hr,
|
||||
max_hr = EXCLUDED.max_hr,
|
||||
avg_pace = EXCLUDED.avg_pace,
|
||||
vo2max = EXCLUDED.vo2max,
|
||||
calories = EXCLUDED.calories,
|
||||
elevation_gain = EXCLUDED.elevation_gain,
|
||||
steps = EXCLUDED.steps,
|
||||
cadence = EXCLUDED.cadence,
|
||||
hr_zone_1 = EXCLUDED.hr_zone_1,
|
||||
hr_zone_2 = EXCLUDED.hr_zone_2,
|
||||
hr_zone_3 = EXCLUDED.hr_zone_3,
|
||||
hr_zone_4 = EXCLUDED.hr_zone_4,
|
||||
hr_zone_5 = EXCLUDED.hr_zone_5
|
||||
""", (
|
||||
a.get("activityId"),
|
||||
a.get("activityName"),
|
||||
a.get("activityType", {}).get("typeKey"),
|
||||
a.get("startTimeLocal"),
|
||||
a.get("duration"),
|
||||
a.get("distance"),
|
||||
a.get("averageHR"),
|
||||
a.get("maxHR"),
|
||||
a.get("averageSpeed"),
|
||||
a.get("vO2MaxValue"),
|
||||
a.get("calories"),
|
||||
a.get("elevationGain"),
|
||||
a.get("steps"),
|
||||
a.get("averageRunningCadenceInStepsPerMinute"),
|
||||
a.get("hrTimeInZone_1"),
|
||||
a.get("hrTimeInZone_2"),
|
||||
a.get("hrTimeInZone_3"),
|
||||
a.get("hrTimeInZone_4"),
|
||||
a.get("hrTimeInZone_5"),
|
||||
))
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
print(f"Synced {len(activities)} activities")
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
print(f"Synced {len(activities)} activities")
|
||||
|
||||
Reference in New Issue
Block a user