aboutsummaryrefslogtreecommitdiff
path: root/web/views.go
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-08-23 11:44:41 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-08-23 11:44:41 +0200
commitd0875a51b2f07766b339b34a580d4e6e9fab348d (patch)
tree2e03e2714afdbf81c05662edc511b0b8b04c7919 /web/views.go
parentf7264b8f594859c1430bd13e765db03002842d38 (diff)
Handle Strava rate limiting with abort, retry time and daily usage display
Strava sync for 167 rides exceeds the 100/15-min read limit (2 calls per ride). Previously a 429 was treated as a skipped ride, so every remaining ride also failed silently. Now GetJSON returns a typed RateLimitError with RetryAfter computed from Retry-After/Date and X-RateLimit headers (15-min window resets at :00/:15/:30/:45, daily at midnight UTC) and tracks Read/Overall usage. syncRides aborts on 429 with partial progress instead of skipping, and handleSync emits an SSE error with retry time, daily usage vs limit and structured rateLimit snapshot; progress and complete events also carry the snapshot for the UI to display. Frontend shows Read daily/15-min usage in progress details and on completion.
Diffstat (limited to 'web/views.go')
-rw-r--r--web/views.go15
1 files changed, 11 insertions, 4 deletions
diff --git a/web/views.go b/web/views.go
index 6fd5adf..cfb31e5 100644
--- a/web/views.go
+++ b/web/views.go
@@ -9,6 +9,7 @@ import (
"github.com/martinlehoux/biking_home/official_climb"
"github.com/martinlehoux/biking_home/ride"
"github.com/martinlehoux/biking_home/rideanalysis"
+ "github.com/martinlehoux/biking_home/strava"
)
type RideView struct {
@@ -376,11 +377,17 @@ type SyncPageData struct {
HasAuth bool
}
+type RateLimitSnapshot struct {
+ Read strava.RateLimit `json:"read"`
+ Overall strava.RateLimit `json:"overall"`
+}
+
type SyncProgress struct {
- Total int `json:"total"`
- Completed int `json:"completed"`
- Imported int `json:"imported"`
- Skipped int `json:"skipped"`
+ Total int `json:"total"`
+ Completed int `json:"completed"`
+ Imported int `json:"imported"`
+ Skipped int `json:"skipped"`
+ RateLimit *RateLimitSnapshot `json:"rateLimit,omitempty"`
}
func formatRideDate(value time.Time) string {