mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Merge pull request #4261 from Spacetech/music_brainz_provider_thread_safe
Make MusicBrainzAlbumProvider thread safe and fix retry logic
This commit is contained in:
commit
19c2abb50f
@ -46,6 +46,7 @@ namespace MediaBrowser.Providers.Music
|
|||||||
|
|
||||||
private readonly string _musicBrainzBaseUrl;
|
private readonly string _musicBrainzBaseUrl;
|
||||||
|
|
||||||
|
private SemaphoreSlim _apiRequestLock = new SemaphoreSlim(1, 1);
|
||||||
private Stopwatch _stopWatchMusicBrainz = new Stopwatch();
|
private Stopwatch _stopWatchMusicBrainz = new Stopwatch();
|
||||||
|
|
||||||
public MusicBrainzAlbumProvider(
|
public MusicBrainzAlbumProvider(
|
||||||
@ -742,18 +743,13 @@ namespace MediaBrowser.Providers.Music
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal async Task<HttpResponseMessage> GetMusicBrainzResponse(string url, CancellationToken cancellationToken)
|
internal async Task<HttpResponseMessage> GetMusicBrainzResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
using var options = new HttpRequestMessage(HttpMethod.Get, _musicBrainzBaseUrl.TrimEnd('/') + url);
|
await _apiRequestLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// MusicBrainz request a contact email address is supplied, as comment, in user agent field:
|
|
||||||
// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting#User-Agent
|
|
||||||
options.Headers.UserAgent.ParseAdd(string.Format(
|
|
||||||
CultureInfo.InvariantCulture,
|
|
||||||
"{0} ( {1} )",
|
|
||||||
_appHost.ApplicationUserAgent,
|
|
||||||
_appHost.ApplicationUserAgentAddress));
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
HttpResponseMessage response;
|
HttpResponseMessage response;
|
||||||
var attempts = 0u;
|
var attempts = 0u;
|
||||||
|
var requestUrl = _musicBrainzBaseUrl.TrimEnd('/') + url;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -761,7 +757,7 @@ namespace MediaBrowser.Providers.Music
|
|||||||
|
|
||||||
if (_stopWatchMusicBrainz.ElapsedMilliseconds < _musicBrainzQueryIntervalMs)
|
if (_stopWatchMusicBrainz.ElapsedMilliseconds < _musicBrainzQueryIntervalMs)
|
||||||
{
|
{
|
||||||
// MusicBrainz is extremely adamant about limiting to one request per second
|
// MusicBrainz is extremely adamant about limiting to one request per second.
|
||||||
var delayMs = _musicBrainzQueryIntervalMs - _stopWatchMusicBrainz.ElapsedMilliseconds;
|
var delayMs = _musicBrainzQueryIntervalMs - _stopWatchMusicBrainz.ElapsedMilliseconds;
|
||||||
await Task.Delay((int)delayMs, cancellationToken).ConfigureAwait(false);
|
await Task.Delay((int)delayMs, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -771,20 +767,35 @@ namespace MediaBrowser.Providers.Music
|
|||||||
_logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds);
|
_logger.LogDebug("GetMusicBrainzResponse: Time since previous request: {0} ms", _stopWatchMusicBrainz.ElapsedMilliseconds);
|
||||||
_stopWatchMusicBrainz.Restart();
|
_stopWatchMusicBrainz.Restart();
|
||||||
|
|
||||||
response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(options).ConfigureAwait(false);
|
using var request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
|
||||||
|
|
||||||
// We retry a finite number of times, and only whilst MB is indicating 503 (throttling)
|
// MusicBrainz request a contact email address is supplied, as comment, in user agent field:
|
||||||
|
// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting#User-Agent .
|
||||||
|
request.Headers.UserAgent.ParseAdd(string.Format(
|
||||||
|
CultureInfo.InvariantCulture,
|
||||||
|
"{0} ( {1} )",
|
||||||
|
_appHost.ApplicationUserAgent,
|
||||||
|
_appHost.ApplicationUserAgentAddress));
|
||||||
|
|
||||||
|
response = await _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(request).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// We retry a finite number of times, and only whilst MB is indicating 503 (throttling).
|
||||||
}
|
}
|
||||||
while (attempts < MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable);
|
while (attempts < MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable);
|
||||||
|
|
||||||
// Log error if unable to query MB database due to throttling
|
// Log error if unable to query MB database due to throttling.
|
||||||
if (attempts == MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable)
|
if (attempts == MusicBrainzQueryAttempts && response.StatusCode == HttpStatusCode.ServiceUnavailable)
|
||||||
{
|
{
|
||||||
_logger.LogError("GetMusicBrainzResponse: 503 Service Unavailable (throttled) response received {0} times whilst requesting {1}", attempts, options.RequestUri);
|
_logger.LogError("GetMusicBrainzResponse: 503 Service Unavailable (throttled) response received {0} times whilst requesting {1}", attempts, requestUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_apiRequestLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user