diff --git a/src/Podsync/Controllers/FeedController.cs b/src/Podsync/Controllers/FeedController.cs index d0e2cb9..fcaf435 100644 --- a/src/Podsync/Controllers/FeedController.cs +++ b/src/Podsync/Controllers/FeedController.cs @@ -27,11 +27,13 @@ namespace Podsync.Controllers private readonly ILinkService _linkService; private readonly IFeedService _feedService; + private readonly IStorageService _storageService; - public FeedController(IRssBuilder rssBuilder, ILinkService linkService, IStorageService storageService, IFeedService feedService) + public FeedController(IRssBuilder rssBuilder, ILinkService linkService, IStorageService storageService, IFeedService feedService, IStorageService storageService1) { _linkService = linkService; _feedService = feedService; + _storageService = storageService1; } [HttpPost] @@ -73,32 +75,41 @@ namespace Podsync.Controllers [ValidateModelState] public async Task Feed([Required] string feedId) { - Feed feed; + var serializedFeed = await _storageService.GetCached(Constants.Cache.FeedsPrefix, feedId); - try + if (string.IsNullOrEmpty(serializedFeed)) { - feed = await _feedService.Get(feedId); - } - catch (KeyNotFoundException) - { - return NotFound($"ERROR: No feed with id {feedId}"); + Feed feed; + + try + { + feed = await _feedService.Get(feedId); + } + catch (KeyNotFoundException) + { + return NotFound($"ERROR: No feed with id {feedId}"); + } + + var selfHost = Request.GetBaseUrl(); + + // Set atom link to this feed + // See https://validator.w3.org/feed/docs/warning/MissingAtomSelfLink.html + var selfLink = new Uri(selfHost, Request.Path); + feed.Channels.ForEach(x => x.AtomLink = selfLink); + + // No magic here, just make download links to DownloadController.Download + feed.Channels.SelectMany(x => x.Items).ForEach(item => + { + var ext = Extensions[item.ContentType]; + item.DownloadLink = new Uri(selfHost, $"download/{feedId}/{item.Id}.{ext}"); + }); + + serializedFeed = feed.ToString(); + + await _storageService.Cache(Constants.Cache.FeedsPrefix, feedId, serializedFeed, TimeSpan.FromMinutes(3)); } - var selfHost = Request.GetBaseUrl(); - - // Set atom link to this feed - // See https://validator.w3.org/feed/docs/warning/MissingAtomSelfLink.html - var selfLink = new Uri(selfHost, Request.Path); - feed.Channels.ForEach(x => x.AtomLink = selfLink); - - // No magic here, just make download links to DownloadController.Download - feed.Channels.SelectMany(x => x.Items).ForEach(item => - { - var ext = Extensions[item.ContentType]; - item.DownloadLink = new Uri(selfHost, $"download/{feedId}/{item.Id}.{ext}"); - }); - - return Content(feed.ToString(), "application/rss+xml; charset=UTF-8"); + return Content(serializedFeed, "application/rss+xml; charset=UTF-8"); } } } \ No newline at end of file diff --git a/src/Podsync/Services/Constants.cs b/src/Podsync/Services/Constants.cs index 303680f..6467b09 100644 --- a/src/Podsync/Services/Constants.cs +++ b/src/Podsync/Services/Constants.cs @@ -27,5 +27,12 @@ namespace Podsync.Services public const int UnhandledError = 3; } + + public static class Cache + { + public const string VideosPrefix = "video_urls"; + + public const string FeedsPrefix = "feeds"; + } } } \ No newline at end of file diff --git a/src/Podsync/Services/Resolver/CachedResolver.cs b/src/Podsync/Services/Resolver/CachedResolver.cs index 7a55a0c..bc38dc5 100644 --- a/src/Podsync/Services/Resolver/CachedResolver.cs +++ b/src/Podsync/Services/Resolver/CachedResolver.cs @@ -6,8 +6,6 @@ namespace Podsync.Services.Resolver { public abstract class CachedResolver : IResolverService { - private const string CachePrefix = "video_urls"; - private readonly TimeSpan UrlExpiration = TimeSpan.FromHours(3); private readonly IStorageService _storageService; @@ -23,7 +21,7 @@ namespace Podsync.Services.Resolver var id = videoUrl.GetHashCode().ToString(); // Check if this video URL was resolved within last 3 hours - var value = await _storageService.GetCached(CachePrefix, id); + var value = await _storageService.GetCached(Constants.Cache.VideosPrefix, id); if (!string.IsNullOrWhiteSpace(value)) { return new Uri(value); @@ -31,7 +29,7 @@ namespace Podsync.Services.Resolver // Resolve and save to cache var uri = await ResolveInternal(videoUrl, format); - await _storageService.Cache(CachePrefix, id, uri.ToString(), UrlExpiration); + await _storageService.Cache(Constants.Cache.VideosPrefix, id, uri.ToString(), UrlExpiration); return uri; } diff --git a/test/Podsync.Tests/Services/Resolver/YtdlWrapperTests.cs b/test/Podsync.Tests/Services/Resolver/YtdlWrapperTests.cs index b072a98..7c90d3b 100644 --- a/test/Podsync.Tests/Services/Resolver/YtdlWrapperTests.cs +++ b/test/Podsync.Tests/Services/Resolver/YtdlWrapperTests.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Moq; +using Podsync.Services; using Podsync.Services.Resolver; using Podsync.Services.Storage; using Xunit; @@ -30,8 +31,8 @@ namespace Podsync.Tests.Services.Resolver var videoUrl = new Uri(url); var downloadUrl = await _resolver.Resolve(videoUrl); - _storage.Verify(x => x.GetCached("video_urls", videoUrl.GetHashCode().ToString()), Times.Once); - _storage.Verify(x => x.Cache("video_urls", videoUrl.GetHashCode().ToString(), It.IsAny(), It.IsAny()), Times.Once); + _storage.Verify(x => x.GetCached(Constants.Cache.VideosPrefix, videoUrl.GetHashCode().ToString()), Times.Once); + _storage.Verify(x => x.Cache(Constants.Cache.VideosPrefix, videoUrl.GetHashCode().ToString(), It.IsAny(), It.IsAny()), Times.Once); Assert.NotEqual(downloadUrl, videoUrl); Assert.True(downloadUrl.IsAbsoluteUri);