Skip to content

Commit feee9f8

Browse files
committed
fix: remove SemaphoreSlim throttle - unnecessary given TMDB rate limits
TMDB allows ~40 requests/10 seconds. The discover page makes at most ~20-30 calls on a completely cold cache, and most endpoints are already cached at the controller level (12h TTL). The semaphore added complexity and contention without meaningful benefit. Task.WhenAll now runs freely - the existing multi-layer caching (controller + engine) is sufficient to keep TMDB call volume low.
1 parent 4e41ce6 commit feee9f8

3 files changed

Lines changed: 10 additions & 69 deletions

File tree

src/Ombi.Core/Engine/BaseMediaEngine.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
using Ombi.Store.Repository;
1818
using Ombi.Api.External.ExternalApis.TheMovieDb.Models;
1919
using Ombi.Core.Helpers;
20-
using System.Threading;
2120

2221
namespace Ombi.Core.Engine
2322
{
@@ -27,11 +26,6 @@ public abstract class BaseMediaEngine : BaseEngine
2726
private Dictionary<int, MovieRequests> _dbMovies;
2827
private Dictionary<int, TvRequests> _dbTv;
2928

30-
/// <summary>
31-
/// Shared throttle for external TMDB API calls across all engine instances.
32-
/// </summary>
33-
protected static readonly SemaphoreSlim ApiThrottle = new SemaphoreSlim(5, 5);
34-
3529
protected BaseMediaEngine(ICurrentUser identity, IRequestServiceMain requestService,
3630
IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub) : base(identity, um, rules)
3731
{

src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -259,18 +259,8 @@ public async Task<IEnumerable<SearchMovieViewModel>> RecentlyRequestedMovies(int
259259
var movieDBResults = await Cache.GetOrAddAsync(nameof(RecentlyRequestedMovies) + toLoad + langCode,
260260
async () =>
261261
{
262-
var tasks = requestResult.Collection.Select(async movie =>
263-
{
264-
await ApiThrottle.WaitAsync();
265-
try
266-
{
267-
return await MovieApi.GetMovieInformation(movie.TheMovieDbId);
268-
}
269-
finally
270-
{
271-
ApiThrottle.Release();
272-
}
273-
});
262+
var tasks = requestResult.Collection.Select(movie =>
263+
MovieApi.GetMovieInformation(movie.TheMovieDbId));
274264
return (await Task.WhenAll(tasks)).ToList();
275265
}, DateTimeOffset.Now.AddHours(12));
276266

@@ -461,18 +451,7 @@ private async Task<SearchMovieViewModel> ProcessSingleMovie(SearchMovieViewModel
461451
if (viewMovie.ImdbId.IsNullOrEmpty())
462452
{
463453
var showInfo = await Cache.GetOrAddAsync("GetMovieInformationWIthImdbId" + viewMovie.Id,
464-
async () =>
465-
{
466-
await ApiThrottle.WaitAsync();
467-
try
468-
{
469-
return await MovieApi.GetMovieInformation(viewMovie.Id);
470-
}
471-
finally
472-
{
473-
ApiThrottle.Release();
474-
}
475-
}, DateTimeOffset.Now.AddHours(12));
454+
() => MovieApi.GetMovieInformation(viewMovie.Id), DateTimeOffset.Now.AddHours(12));
476455
viewMovie.Id = showInfo.Id; // TheMovieDbId
477456
viewMovie.ImdbId = showInfo.ImdbId;
478457
}

src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -199,18 +199,8 @@ public async Task<IEnumerable<SearchFullInfoTvShowViewModel>> RecentlyRequestedS
199199
var movieDBResults = await Cache.GetOrAddAsync(nameof(RecentlyRequestedShows) + toLoad + langCode,
200200
async () =>
201201
{
202-
var tasks = requestResult.Collection.Select(async movie =>
203-
{
204-
await ApiThrottle.WaitAsync();
205-
try
206-
{
207-
return await _movieApi.GetTVInfo(movie.ExternalProviderId.ToString());
208-
}
209-
finally
210-
{
211-
ApiThrottle.Release();
212-
}
213-
});
202+
var tasks = requestResult.Collection.Select(movie =>
203+
_movieApi.GetTVInfo(movie.ExternalProviderId.ToString()));
214204
return (await Task.WhenAll(tasks)).ToList();
215205
}, DateTimeOffset.Now.AddHours(12));
216206

@@ -240,36 +230,14 @@ private async Task<IEnumerable<SearchTvShowViewModel>> ProcessResults(List<Movie
240230
var enrichTasks = nonDemoItems.Select(async tvMazeSearch =>
241231
{
242232
var show = await Cache.GetOrAddAsync(nameof(GetShowInformation) + tvMazeSearch.Id.ToString(),
243-
async () =>
244-
{
245-
await ApiThrottle.WaitAsync();
246-
try
247-
{
248-
return await _movieApi.GetTVInfo(tvMazeSearch.Id.ToString());
249-
}
250-
finally
251-
{
252-
ApiThrottle.Release();
253-
}
254-
}, DateTime.Now.AddHours(12));
233+
() => _movieApi.GetTVInfo(tvMazeSearch.Id.ToString()), DateTime.Now.AddHours(12));
255234

256235
// Fetch all season episodes in parallel for this show
257236
var seasons = show.seasons.Where(x => x.season_number != 0).ToList();
258-
var episodeTasks = seasons.Select(async tvSeason =>
259-
{
260-
return await Cache.GetOrAddAsync("SeasonEpisodes" + show.id + tvSeason.season_number, async () =>
261-
{
262-
await ApiThrottle.WaitAsync();
263-
try
264-
{
265-
return await _movieApi.GetSeasonEpisodes(show.id, tvSeason.season_number, CancellationToken.None);
266-
}
267-
finally
268-
{
269-
ApiThrottle.Release();
270-
}
271-
}, DateTimeOffset.Now.AddHours(12));
272-
});
237+
var episodeTasks = seasons.Select(tvSeason =>
238+
Cache.GetOrAddAsync("SeasonEpisodes" + show.id + tvSeason.season_number,
239+
() => _movieApi.GetSeasonEpisodes(show.id, tvSeason.season_number, CancellationToken.None),
240+
DateTimeOffset.Now.AddHours(12)));
273241
var episodeResults = await Task.WhenAll(episodeTasks);
274242

275243
// Map seasons sequentially per show (mutates SeasonRequests)

0 commit comments

Comments
 (0)