feat: auto-retry uploads when rate limited (v0.13.0)

Backend: rate limiter gains check_with_retry() returning seconds until
the next slot opens. Upload 429 responses include retry_after_secs in
JSON and a Retry-After header.

Frontend: upload queue catches 429 as RateLimitError, resets affected
item to pending, schedules processQueue() for the server-reported delay,
and shows a live countdown banner in the queue UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-04-03 18:37:51 +02:00
parent 3dc69e6c6d
commit de0e395a9e
8 changed files with 113 additions and 24 deletions

View File

@@ -20,13 +20,14 @@ pub async fn upload(
) -> Result<(StatusCode, Json<UploadDto>), AppError> {
// Rate limit: N uploads per hour per user
let upload_rate = get_config_i64(&state.pool, "upload_rate_per_hour", 10).await as usize;
if !state
if let Err(retry_after_secs) = state
.rate_limiter
.check(format!("upload:{}", auth.user_id), upload_rate, Duration::from_secs(3600))
.check_with_retry(format!("upload:{}", auth.user_id), upload_rate, Duration::from_secs(3600))
{
drain_multipart(multipart).await;
return Err(AppError::TooManyRequests(
"Du hast dein Upload-Limit für diese Stunde erreicht.".into(),
Some(retry_after_secs),
));
}