Fix segment effort duplicates; auto-scan on segment creation
- detect.py: truncate started_at to seconds so dedup key survives JSON round-trip - store.py: dedup by (activity_id, iso-started_at) string key, not object equality - server.py: extract _scan_segment_for_user helper; trigger background scan for the creating user's activities when a new segment is saved
This commit is contained in:
+27
-19
@@ -23,7 +23,7 @@ from typing import Any, Optional
|
||||
|
||||
log = logging.getLogger("bincio.serve")
|
||||
|
||||
from fastapi import Cookie, Depends, FastAPI, File, Form, HTTPException, Request, Response, UploadFile
|
||||
from fastapi import BackgroundTasks, Cookie, Depends, FastAPI, File, Form, HTTPException, Request, Response, UploadFile
|
||||
from fastapi.responses import FileResponse, RedirectResponse, StreamingResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.middleware.gzip import GZipMiddleware
|
||||
@@ -2459,6 +2459,7 @@ async def get_segment(segment_id: str) -> JSONResponse:
|
||||
@app.post("/api/segments")
|
||||
async def create_segment(
|
||||
body: CreateSegmentRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
bincio_session: Optional[str] = Cookie(default=None),
|
||||
) -> JSONResponse:
|
||||
user = _require_user(bincio_session)
|
||||
@@ -2483,7 +2484,9 @@ async def create_segment(
|
||||
created_by=user.handle,
|
||||
created_at=datetime.now(_tz.utc),
|
||||
)
|
||||
_seg_store.save_segment(_get_data_dir(), seg)
|
||||
dd = _get_data_dir()
|
||||
_seg_store.save_segment(dd, seg)
|
||||
background_tasks.add_task(_scan_segment_for_user, dd, user.handle, seg_id)
|
||||
return JSONResponse({"id": seg_id}, status_code=201)
|
||||
|
||||
|
||||
@@ -2529,30 +2532,22 @@ async def get_segment_efforts(
|
||||
])
|
||||
|
||||
|
||||
@app.post("/api/segments/{segment_id}/detect")
|
||||
async def trigger_detect(
|
||||
segment_id: str,
|
||||
bincio_session: Optional[str] = Cookie(default=None),
|
||||
) -> JSONResponse:
|
||||
"""Retroactively detect efforts on a segment for the logged-in user."""
|
||||
user = _require_user(bincio_session)
|
||||
dd = _get_data_dir()
|
||||
seg = _seg_store.load_segment(dd, segment_id)
|
||||
if seg is None:
|
||||
raise HTTPException(404, "Segment not found")
|
||||
|
||||
def _scan_segment_for_user(dd: Path, handle: str, segment_id: str) -> int:
|
||||
"""Scan all of a user's activities against one segment. Returns effort count."""
|
||||
from datetime import datetime as _datetime
|
||||
from bincio.segments.detect import track_from_timeseries_json, detect_one
|
||||
import json as _json
|
||||
|
||||
user_dir = dd / user.handle
|
||||
seg = _seg_store.load_segment(dd, segment_id)
|
||||
if seg is None:
|
||||
return 0
|
||||
user_dir = dd / handle
|
||||
acts_dir = user_dir / "activities"
|
||||
total = 0
|
||||
for detail_path in sorted(acts_dir.glob("*.json")):
|
||||
if ".timeseries." in detail_path.name:
|
||||
continue
|
||||
try:
|
||||
detail = _json.loads(detail_path.read_text(encoding="utf-8"))
|
||||
detail = json.loads(detail_path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
continue
|
||||
ts_url = detail.get("timeseries_url")
|
||||
@@ -2562,7 +2557,7 @@ async def trigger_detect(
|
||||
if not ts_path.exists():
|
||||
continue
|
||||
try:
|
||||
ts = _json.loads(ts_path.read_text(encoding="utf-8"))
|
||||
ts = json.loads(ts_path.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
continue
|
||||
started_raw = detail.get("started_at")
|
||||
@@ -2578,9 +2573,22 @@ async def trigger_detect(
|
||||
continue
|
||||
efforts = detect_one(track, seg)
|
||||
for effort in efforts:
|
||||
_seg_store.add_effort(dd, user.handle, segment_id, effort)
|
||||
_seg_store.add_effort(dd, handle, segment_id, effort)
|
||||
total += len(efforts)
|
||||
return total
|
||||
|
||||
|
||||
@app.post("/api/segments/{segment_id}/detect")
|
||||
async def trigger_detect(
|
||||
segment_id: str,
|
||||
bincio_session: Optional[str] = Cookie(default=None),
|
||||
) -> JSONResponse:
|
||||
"""Retroactively detect efforts on a segment for the logged-in user."""
|
||||
user = _require_user(bincio_session)
|
||||
dd = _get_data_dir()
|
||||
if _seg_store.load_segment(dd, segment_id) is None:
|
||||
raise HTTPException(404, "Segment not found")
|
||||
total = _scan_segment_for_user(dd, user.handle, segment_id)
|
||||
return JSONResponse({"ok": True, "efforts_found": total})
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user