Skip to content

Commit 67cb3e4

Browse files
NoggogJohnnyCrazy
authored andcommitted
TooManyRequests Handling (JohnnyCrazy#282)
* SpotifyHttpStatusCode A small supplementary enum for Spotify specific codes. Only contains TooManyRequests currently, but more can be added. * TooManyRequests Retry Handling Will now parse and wait the Spotify recommended wait time. Also has the option to not consume a retry attempt on this type of error * TryGetTooManyRequests refactored to GetTooManyRequests To keep the library consistent * Removed SpotifyHttpStatusCode
1 parent fa0f3e2 commit 67cb3e4

4 files changed

Lines changed: 49 additions & 6 deletions

File tree

‎SpotifyAPI.Web/Models/BasicModel.cs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Newtonsoft.Json;
2+
using SpotifyAPI.Web.Enums;
23
using System;
34
using System.Net;
45

‎SpotifyAPI.Web/Models/ResponseInfo.cs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Net;
1+
using SpotifyAPI.Web.Enums;
2+
using System.Net;
23

34
namespace SpotifyAPI.Web.Models
45
{

‎SpotifyAPI.Web/SpotifyWebAPI.cs‎

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Newtonsoft.Json;
1+
using Newtonsoft.Json;
22
using Newtonsoft.Json.Linq;
33
using SpotifyAPI.Web.Enums;
44
using SpotifyAPI.Web.Models;
@@ -78,6 +78,11 @@ public void Dispose()
7878
/// </summary>
7979
public int RetryTimes { get; set; } = 10;
8080

81+
/// <summary>
82+
/// Whether a failure of type "Too Many Requests" should use up one of the allocated retry attempts.
83+
/// </summary>
84+
public bool TooManyRequestsConsumesARetry { get; set; } = false;
85+
8186
/// <summary>
8287
/// Error codes that will trigger auto-retry if <see cref="UseAutoRetry"/> is enabled.
8388
/// </summary>
@@ -2445,6 +2450,26 @@ public T DownloadData<T>(string url) where T : BasicModel
24452450
return response.Item2;
24462451
}
24472452

2453+
/// <summary>
2454+
/// Retrieves whether request had a "TooManyRequests" error, and get the amount Spotify recommends waiting before another request.
2455+
/// </summary>
2456+
/// <param name="info">Info object to analyze.</param>
2457+
/// <returns>Seconds to wait before making another request. -1 if no error.</returns>
2458+
/// <remarks>AUTH NEEDED</remarks>
2459+
private int GetTooManyRequests(ResponseInfo info)
2460+
{
2461+
// 429 is "TooManyRequests" value specified in Spotify API
2462+
if (429 != (int)info.StatusCode)
2463+
{
2464+
return -1;
2465+
}
2466+
if (!int.TryParse(info.Headers.Get("Retry-After"), out var secondsToWait))
2467+
{
2468+
return -1;
2469+
}
2470+
return secondsToWait;
2471+
}
2472+
24482473
public async Task<T> DownloadDataAsync<T>(string url) where T : BasicModel
24492474
{
24502475
int triesLeft = RetryTimes + 1;
@@ -2453,15 +2478,30 @@ public async Task<T> DownloadDataAsync<T>(string url) where T : BasicModel
24532478
Tuple<ResponseInfo, T> response = null;
24542479
do
24552480
{
2456-
if (response != null) { await Task.Delay(RetryAfter).ConfigureAwait(false); }
2481+
if (response != null)
2482+
{
2483+
int msToWait = RetryAfter;
2484+
var secondsToWait = GetTooManyRequests(response.Item1);
2485+
if (secondsToWait > 0)
2486+
{
2487+
msToWait = secondsToWait * 1000;
2488+
}
2489+
await Task.Delay(msToWait).ConfigureAwait(false);
2490+
}
24572491
response = await DownloadDataAltAsync<T>(url).ConfigureAwait(false);
24582492

24592493
response.Item2.AddResponseInfo(response.Item1);
24602494
lastError = response.Item2.Error;
24612495

2462-
triesLeft -= 1;
2496+
if (TooManyRequestsConsumesARetry || GetTooManyRequests(response.Item1) == -1)
2497+
{
2498+
triesLeft -= 1;
2499+
}
24632500

2464-
} while (UseAutoRetry && triesLeft > 0 && lastError != null && RetryErrorCodes.Contains(lastError.Status));
2501+
} while (UseAutoRetry
2502+
&& triesLeft > 0
2503+
&& (GetTooManyRequests(response.Item1) != -1
2504+
|| (lastError != null && RetryErrorCodes.Contains(lastError.Status))));
24652505

24662506

24672507
return response.Item2;

‎SpotifyAPI.Web/SpotifyWebClient.cs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Newtonsoft.Json;
1+
using Newtonsoft.Json;
22
using System;
33
using System.Collections.Generic;
44
using System.Net;
@@ -7,6 +7,7 @@
77
using System.Text;
88
using System.Threading.Tasks;
99
using SpotifyAPI.Web.Models;
10+
using SpotifyAPI.Web.Enums;
1011

1112
namespace SpotifyAPI.Web
1213
{

0 commit comments

Comments
 (0)