feat: auto-retry uploads when rate limited
Backend: extend rate limiter with check_with_retry() that returns the seconds until the next slot opens. Upload 429 responses now include retry_after_secs in the JSON body and a Retry-After header. Frontend: the upload queue catches 429s as RateLimitError, resets the affected item to pending, schedules processQueue() to resume after the server-reported wait, and shows a live countdown banner in UploadQueue. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user