mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-09 07:10:34 +02:00
Only delay making request if necessary
When requesting data from MusicBrainz, only delay the request if previous request was less than rate limit ago, instead of always delaying for one second at start.
This commit is contained in:
parent
208585d3f6
commit
6d3e6d800f
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -28,6 +29,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
private readonly IApplicationHost _appHost;
|
private readonly IApplicationHost _appHost;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IJsonSerializer _json;
|
private readonly IJsonSerializer _json;
|
||||||
|
private Stopwatch _stopWatchMusicBrainz = new Stopwatch();
|
||||||
|
|
||||||
public readonly string MusicBrainzBaseUrl;
|
public readonly string MusicBrainzBaseUrl;
|
||||||
|
|
||||||
|
@ -45,6 +47,9 @@ namespace MediaBrowser.Providers.Music
|
||||||
|
|
||||||
MusicBrainzBaseUrl = configuration["MusicBrainz:BaseUrl"];
|
MusicBrainzBaseUrl = configuration["MusicBrainz:BaseUrl"];
|
||||||
|
|
||||||
|
// Use a stopwatch to ensure we don't exceed the MusicBrainz rate limit
|
||||||
|
_stopWatchMusicBrainz.Start();
|
||||||
|
|
||||||
Current = this;
|
Current = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,8 +59,6 @@ namespace MediaBrowser.Providers.Music
|
||||||
var releaseGroupId = searchInfo.GetReleaseGroupId();
|
var releaseGroupId = searchInfo.GetReleaseGroupId();
|
||||||
|
|
||||||
string url;
|
string url;
|
||||||
var isNameSearch = false;
|
|
||||||
bool forceMusicBrainzProper = false;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(releaseId))
|
if (!string.IsNullOrEmpty(releaseId))
|
||||||
{
|
{
|
||||||
|
@ -64,7 +67,6 @@ namespace MediaBrowser.Providers.Music
|
||||||
else if (!string.IsNullOrEmpty(releaseGroupId))
|
else if (!string.IsNullOrEmpty(releaseGroupId))
|
||||||
{
|
{
|
||||||
url = string.Format("/ws/2/release?release-group={0}", releaseGroupId);
|
url = string.Format("/ws/2/release?release-group={0}", releaseGroupId);
|
||||||
forceMusicBrainzProper = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -78,8 +80,6 @@ namespace MediaBrowser.Providers.Music
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
isNameSearch = true;
|
|
||||||
|
|
||||||
// I'm sure there is a better way but for now it resolves search for 12" Mixes
|
// I'm sure there is a better way but for now it resolves search for 12" Mixes
|
||||||
var queryName = searchInfo.Name.Replace("\"", string.Empty);
|
var queryName = searchInfo.Name.Replace("\"", string.Empty);
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(url))
|
if (!string.IsNullOrWhiteSpace(url))
|
||||||
{
|
{
|
||||||
using (var response = await GetMusicBrainzResponse(url, isNameSearch, forceMusicBrainzProper, cancellationToken).ConfigureAwait(false))
|
using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
{
|
{
|
||||||
|
@ -247,7 +247,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
WebUtility.UrlEncode(albumName),
|
WebUtility.UrlEncode(albumName),
|
||||||
artistId);
|
artistId);
|
||||||
|
|
||||||
using (var response = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||||
{
|
{
|
||||||
|
@ -272,7 +272,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
WebUtility.UrlEncode(albumName),
|
WebUtility.UrlEncode(albumName),
|
||||||
WebUtility.UrlEncode(artistName));
|
WebUtility.UrlEncode(artistName));
|
||||||
|
|
||||||
using (var response = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||||
{
|
{
|
||||||
|
@ -589,7 +589,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
var url = string.Format("/ws/2/release?release-group={0}", releaseGroupId);
|
var url = string.Format("/ws/2/release?release-group={0}", releaseGroupId);
|
||||||
|
|
||||||
using (var response = await GetMusicBrainzResponse(url, true, true, cancellationToken).ConfigureAwait(false))
|
using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||||
{
|
{
|
||||||
|
@ -625,7 +625,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
|
var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
|
||||||
|
|
||||||
using (var response = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
|
using (var response = await GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
using (var oReader = new StreamReader(stream, Encoding.UTF8))
|
||||||
{
|
{
|
||||||
|
@ -710,34 +710,32 @@ namespace MediaBrowser.Providers.Music
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Task<HttpResponseInfo> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return GetMusicBrainzResponse(url, isSearch, false, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the music brainz response.
|
/// Makes request to MusicBrainz server and awaits a response.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal async Task<HttpResponseInfo> GetMusicBrainzResponse(string url, bool isSearch, bool forceMusicBrainzProper, CancellationToken cancellationToken)
|
internal async Task<HttpResponseInfo> GetMusicBrainzResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var urlInfo = new MbzUrl(MusicBrainzBaseUrl, 1000);
|
// The Jellyfin user-agent is unrestricted but source IP must not exceed
|
||||||
var throttleMs = urlInfo.throttleMs;
|
// one request per second, therefore we rate limit to avoid throttling
|
||||||
|
// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
|
||||||
|
const long QueryIntervalMs = 1000u;
|
||||||
|
|
||||||
if (throttleMs > 0)
|
// Only delay if necessary
|
||||||
|
if (_stopWatchMusicBrainz.ElapsedMilliseconds < QueryIntervalMs)
|
||||||
{
|
{
|
||||||
// MusicBrainz is extremely adamant about limiting to one request per second
|
var delayMs = QueryIntervalMs - _stopWatchMusicBrainz.ElapsedMilliseconds;
|
||||||
_logger.LogDebug("Throttling MusicBrainz by {0}ms", throttleMs.ToString(CultureInfo.InvariantCulture));
|
await Task.Delay((int)delayMs, cancellationToken).ConfigureAwait(false);
|
||||||
await Task.Delay(throttleMs, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
url = urlInfo.url.TrimEnd('/') + url;
|
_logger.LogDebug("MusicBrainz time since previous request: {0}ms", _stopWatchMusicBrainz.ElapsedMilliseconds);
|
||||||
|
_stopWatchMusicBrainz.Restart();
|
||||||
|
|
||||||
var options = new HttpRequestOptions
|
var options = new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = url,
|
Url = MusicBrainzBaseUrl.TrimEnd('/') + url,
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
UserAgent = _appHost.ApplicationUserAgent,
|
UserAgent = _appHost.ApplicationUserAgent,
|
||||||
BufferContent = throttleMs > 0
|
BufferContent = false
|
||||||
};
|
};
|
||||||
|
|
||||||
return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
|
||||||
|
@ -749,17 +747,5 @@ namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class MbzUrl
|
|
||||||
{
|
|
||||||
internal MbzUrl(string url, int throttleMs)
|
|
||||||
{
|
|
||||||
this.url = url;
|
|
||||||
this.throttleMs = throttleMs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string url { get; set; }
|
|
||||||
public int throttleMs { get; set; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
{
|
{
|
||||||
var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId);
|
var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId);
|
||||||
|
|
||||||
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
|
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
{
|
{
|
||||||
|
@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
|
|
||||||
var url = string.Format("/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
|
var url = string.Format("/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
|
||||||
|
|
||||||
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
{
|
{
|
||||||
|
@ -64,7 +64,7 @@ namespace MediaBrowser.Providers.Music
|
||||||
// Try again using the search with accent characters url
|
// Try again using the search with accent characters url
|
||||||
url = string.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
|
url = string.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
|
||||||
|
|
||||||
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
|
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
using (var stream = response.Content)
|
using (var stream = response.Content)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue