From 4a61f3eb3103aa512bef1b0d82295403bc4bc977 Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Thu, 27 Aug 2026 19:07:33 +0200 Subject: Swap ride read path from GPX to FIT for performance Always use FIT for detail, official climb creation and backtest; keep GPX fallback for legacy rides pending backfill. FIT is 10-20x smaller and parses without XML. --- web/rides.go | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'web/rides.go') diff --git a/web/rides.go b/web/rides.go index d3f5634..f59c0a4 100644 --- a/web/rides.go +++ b/web/rides.go @@ -51,14 +51,25 @@ func (s *Server) handleRide(w http.ResponseWriter, r *http.Request) { http.NotFound(w, r) return } - if item.GPXPath == "" { + if item.FitPath == "" && item.GPXPath == "" { slog.Info("Loaded ride detail without route", "ride_id", id) kcore.RenderPage(r.Context(), RideDetailPage(RideDetailView{RideView: buildRideView(item), Notice: rideDetailNotice(r)}), w) return } - parsed, err := ride.ParseFile(ride.GPXRideParser{}, item.GPXPath) + // Prefer FIT; fallback to GPX for legacy rides pending backfill. + var parsed ride.Ride + if item.FitPath != "" { + parsed, err = ride.ParseFile(ride.FITRideParser{}, item.FitPath) + if err != nil { + slog.Error("Failed to load ride route", "ride_id", id, "file", item.FitPath, "error", err) + } + } else { + parsed, err = ride.ParseFile(ride.GPXRideParser{}, item.GPXPath) + if err != nil { + slog.Error("Failed to load ride route", "ride_id", id, "file", item.GPXPath, "error", err) + } + } if err != nil { - slog.Error("Failed to load ride route", "ride_id", id, "file", item.GPXPath, "error", err) kcore.RenderPage(r.Context(), RideDetailPage(RideDetailView{ RideView: buildRideView(item), RouteError: "The recorded route is unavailable.", @@ -121,7 +132,7 @@ func (s *Server) handleCreateOfficialClimb(w http.ResponseWriter, r *http.Reques http.NotFound(w, r) return } - if item.GPXPath == "" { + if item.FitPath == "" && item.GPXPath == "" { http.Error(w, "a recorded route is required to create an official climb", http.StatusBadRequest) return } @@ -139,9 +150,19 @@ func (s *Server) handleCreateOfficialClimb(w http.ResponseWriter, r *http.Reques http.Error(w, "a valid end route point is required", http.StatusBadRequest) return } - parsed, err := ride.ParseFile(ride.GPXRideParser{}, item.GPXPath) + var parsed ride.Ride + if item.FitPath != "" { + parsed, err = ride.ParseFile(ride.FITRideParser{}, item.FitPath) + if err != nil { + slog.Error("Failed to load ride route for official climb creation", "ride_id", id, "file", item.FitPath, "error", err) + } + } else { + parsed, err = ride.ParseFile(ride.GPXRideParser{}, item.GPXPath) + if err != nil { + slog.Error("Failed to load ride route for official climb creation", "ride_id", id, "file", item.GPXPath, "error", err) + } + } if err != nil { - slog.Error("Failed to load ride route for official climb creation", "ride_id", id, "file", item.GPXPath, "error", err) http.Error(w, "the recorded route is unavailable", http.StatusBadRequest) return } -- cgit v1.3