diff options
| author | Joshua M. Boniface <joshua@boniface.me> | 2019-03-15 16:47:03 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-03-15 16:47:03 -0400 |
| commit | 59031ee3b8b2ac8298c41f9171b658e3f15e17bc (patch) | |
| tree | 8c24991b035e6e097bac7c5d2869d69300520d52 /MediaBrowser.Providers | |
| parent | 35ff8ec713f4ad9c81e27c54fcc3025d7768367f (diff) | |
| parent | d2e408539ea32eaad573ff1deb6f77a2d80a70d3 (diff) | |
Merge pull request #1119 from ploughpuff/503retry
MusicBrainz 503 Retry Strategy
Diffstat (limited to 'MediaBrowser.Providers')
| -rw-r--r-- | MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs | 63 |
1 files changed, 48 insertions, 15 deletions
diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index b716f40f0..3797f9039 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -32,12 +32,21 @@ namespace MediaBrowser.Providers.Music public readonly string MusicBrainzBaseUrl; - // The Jellyfin user-agent is unrestricted but source IP must not exceed - // one request per second, therefore we rate limit to avoid throttling. - // Be prudent, use a value slightly above the minimun required. - // https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting + /// <summary> + /// The Jellyfin user-agent is unrestricted but source IP must not exceed + /// one request per second, therefore we rate limit to avoid throttling. + /// Be prudent, use a value slightly above the minimun required. + /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting + /// </summary> private const long MusicBrainzQueryIntervalMs = 1050u; + /// <summary> + /// For each single MB lookup/search, this is the maximum number of + /// attempts that shall be made whilst receiving a 503 Server + /// Unavailable (indicating throttled) response. + /// </summary> + private const uint MusicBrainzQueryAttempts = 5u; + public MusicBrainzAlbumProvider( IHttpClient httpClient, IApplicationHost appHost, @@ -717,19 +726,12 @@ namespace MediaBrowser.Providers.Music /// <summary> /// Makes request to MusicBrainz server and awaits a response. + /// A 503 Service Unavailable response indicates throttling to maintain a rate limit. + /// A number of retries shall be made in order to try and satisfy the request before + /// giving up and returning null. /// </summary> internal async Task<HttpResponseInfo> GetMusicBrainzResponse(string url, CancellationToken cancellationToken) { - if (_stopWatchMusicBrainz.ElapsedMilliseconds < MusicBrainzQueryIntervalMs) - { - // MusicBrainz is extremely adamant about limiting to one request per second - var delayMs = MusicBrainzQueryIntervalMs - _stopWatchMusicBrainz.ElapsedMilliseconds; - await Task.Delay((int)delayMs, cancellationToken).ConfigureAwait(false); - } - - _logger.LogDebug("MusicBrainz time since previous request: {0}ms", _stopWatchMusicBrainz.ElapsedMilliseconds); - _stopWatchMusicBrainz.Restart(); - var options = new HttpRequestOptions { Url = MusicBrainzBaseUrl.TrimEnd('/') + url, @@ -740,7 +742,38 @@ namespace MediaBrowser.Providers.Music BufferContent = false }; - return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false); + HttpResponseInfo response; + var attempts = 0u; + + do + { + attempts++; + + if (_stopWatchMusicBrainz.ElapsedMilliseconds < MusicBrainzQueryIntervalMs) + { + // MusicBrainz is extremely adamant about limiting to one request per second + var delayMs = MusicBrainzQueryIntervalMs - _stopWatchMusicBrainz.ElapsedMilliseconds; + await Task.Delay((int)delayMs, cancellationToken).ConfigureAwait(false); + } + + // Write time since last request to debug log as evidence we're meeting rate limit + // requirement, before resetting stopwatch back to zero. + _logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds); + _stopWatchMusicBrainz.Restart(); + + response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false); + + // We retry a finite number of times, and only whilst MB is indcating 503 (throttling) + } + while (attempts < MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable); + + // Log error if unable to query MB database due to throttling + if (attempts == MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable ) + { + _logger.LogError("GetMusicBrainzResponse: 503 Service Unavailable (throttled) response received {0} times whilst requesting {1}", attempts, options.Url); + } + + return response; } public int Order => 0; |
