- "Last sync: never": The old blocking sync was killed by nginx at 120s before save_token was reached. The activities made it to disk (ingestion happens per-activity as it goes), but the token's
last_sync_at timestamp was never written. After deploying, do a soft reset — it'll set last_sync_at to your most recent activity's timestamp so the next sync only fetches newer ones. - Reset 404: Added POST /api/strava/reset to serve/server.py. The soft reset now looks in _merged/index.json first (multi-user path), falling back to index.json.
This commit is contained in:
+57
-8
@@ -663,16 +663,65 @@ async def strava_status(bincio_session: Optional[str] = Cookie(default=None)) ->
|
||||
if not strava_client_id:
|
||||
return JSONResponse({"configured": False, "connected": False, "last_sync": None})
|
||||
dd = _get_data_dir() / user.handle
|
||||
token_path = dd / "strava_token.json"
|
||||
connected = token_path.exists()
|
||||
last_sync = None
|
||||
if connected:
|
||||
from bincio.extract.strava_api import load_token
|
||||
token = load_token(dd)
|
||||
return JSONResponse({
|
||||
"configured": True,
|
||||
"connected": token is not None,
|
||||
"last_sync": token.get("last_sync_at") if token else None,
|
||||
})
|
||||
|
||||
|
||||
@app.post("/api/strava/reset")
|
||||
async def strava_reset(request: Request, bincio_session: Optional[str] = Cookie(default=None)) -> JSONResponse:
|
||||
"""Reset last_sync_at so the next sync re-fetches from a chosen point.
|
||||
|
||||
mode=soft — set to the started_at of the most recent activity on disk
|
||||
(next sync only fetches activities newer than the last known one)
|
||||
mode=hard — clear last_sync_at entirely
|
||||
(next sync re-downloads full Strava history, skipping existing files)
|
||||
"""
|
||||
user = _require_user(bincio_session)
|
||||
dd = _get_data_dir() / user.handle
|
||||
from bincio.extract.strava_api import load_token, save_token
|
||||
token = load_token(dd)
|
||||
if token is None:
|
||||
raise HTTPException(400, "Not connected to Strava")
|
||||
|
||||
body = await request.json()
|
||||
mode = body.get("mode", "soft")
|
||||
|
||||
if mode == "hard":
|
||||
token.pop("last_sync_at", None)
|
||||
save_token(dd, token)
|
||||
return JSONResponse({"ok": True, "mode": "hard", "last_sync_at": None})
|
||||
|
||||
# soft: find the most recent started_at across the user's merged index
|
||||
from datetime import datetime, timezone
|
||||
last_ts: int | None = None
|
||||
for index_path in [dd / "_merged" / "index.json", dd / "index.json"]:
|
||||
if not index_path.exists():
|
||||
continue
|
||||
try:
|
||||
token = json.loads(token_path.read_text())
|
||||
last_sync = token.get("last_sync_at")
|
||||
index_data = json.loads(index_path.read_text(encoding="utf-8"))
|
||||
started_ats = [
|
||||
a.get("started_at") for a in index_data.get("activities", [])
|
||||
if a.get("started_at")
|
||||
]
|
||||
if started_ats:
|
||||
latest = max(started_ats)
|
||||
dt = datetime.fromisoformat(latest.replace("Z", "+00:00"))
|
||||
last_ts = int(dt.astimezone(timezone.utc).timestamp())
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
return JSONResponse({"configured": True, "connected": connected, "last_sync": last_sync})
|
||||
continue
|
||||
|
||||
if last_ts is None:
|
||||
token.pop("last_sync_at", None)
|
||||
else:
|
||||
token["last_sync_at"] = last_ts
|
||||
save_token(dd, token)
|
||||
return JSONResponse({"ok": True, "mode": "soft", "last_sync_at": last_ts})
|
||||
|
||||
|
||||
@app.get("/api/strava/auth-url")
|
||||
|
||||
Reference in New Issue
Block a user