Changed Shop interface to be more asynchronous.

Implemented changes in Props.

Implemented said changes in AdafruitShop.

Fixed and improved caching in AdafruitShop.
This commit is contained in:
2021-08-11 23:54:52 -05:00
parent ff080390f8
commit 8a1e5aca15
12 changed files with 145 additions and 76 deletions

View File

@@ -12,7 +12,7 @@ namespace Props.Shop.Adafruit.Tests.Api
public class FakeProductListingManager : IProductListingManager
{
private bool disposedValue;
private DateTime? lastDownload;
public DateTime? LastDownload { get; private set; }
private ProductListingsParser parser = new ProductListingsParser();
private readonly ConcurrentDictionary<string, ProductListing> activeProductListingUrls = new ConcurrentDictionary<string, ProductListing>();
@@ -29,21 +29,27 @@ namespace Props.Shop.Adafruit.Tests.Api
public void RefreshProductListings()
{
if (disposedValue) throw new ObjectDisposedException("ProductListingManager");
if ((lastDownload != null && DateTime.UtcNow - lastDownload <= TimeSpan.FromMilliseconds(5 * 60 * 1000)) || (ProductListings != null && !ProductListings.IsCompleted)) return;
ProductListings = DownloadListings();
if ((LastDownload != null && DateTime.UtcNow - LastDownload <= TimeSpan.FromMilliseconds(5 * 60 * 1000)) || (ProductListings != null && !ProductListings.IsCompleted)) return;
ProductListings = DownloadListings();
}
private Task<IReadOnlyDictionary<string, IList<ProductListing>>> DownloadListings() {
private Task<IReadOnlyDictionary<string, IList<ProductListing>>> DownloadListings()
{
if (disposedValue) throw new ObjectDisposedException("ProductListingManager");
lastDownload = DateTime.UtcNow;
parser.BuildProductListings(File.OpenRead("./Assets/products.json"));
LastDownload = DateTime.UtcNow;
using (Stream stream = File.OpenRead("./Assets/products.json"))
{
parser.BuildProductListings(stream);
}
Dictionary<string, IList<ProductListing>> listingNames = new Dictionary<string, IList<ProductListing>>();
activeProductListingUrls.Clear();
foreach (ProductListing product in parser.ProductListings)
{
activeProductListingUrls.TryAdd(product.URL, product);
IList<ProductListing> sameProducts = listingNames.GetValueOrDefault(product.Name);
if (sameProducts == null) {
if (sameProducts == null)
{
sameProducts = new List<ProductListing>();
listingNames.Add(product.Name, sameProducts);
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Props.Shop.Adafruit.Api;
using Props.Shop.Adafruit.Persistence;
using Props.Shop.Framework;
using Xunit;
namespace Props.Shop.Adafruit.Tests.Api
{
public class LiveProductListingManagerTest
{
[Fact]
public async Task CacheTest()
{
// TODO: Improve testability of caching system, IProductListingManager, and implement here.
//Given
ProductListingsParser parser = new ProductListingsParser();
using (Stream stream = File.OpenRead("./Assets/products.json"))
{
parser.BuildProductListings(stream);
}
Dictionary<string, IList<ProductListing>> listingNames = new Dictionary<string, IList<ProductListing>>();
foreach (ProductListing product in parser.ProductListings)
{
IList<ProductListing> sameProducts = listingNames.GetValueOrDefault(product.Name);
if (sameProducts == null)
{
sameProducts = new List<ProductListing>();
listingNames.Add(product.Name, sameProducts);
}
sameProducts.Add(product);
}
ProductListingCacheData cache = new ProductListingCacheData(listingNames);
await Task.Delay(500);
LiveProductListingManager mockLiveProductListingManager = new LiveProductListingManager(null, new Logger<LiveProductListingManager>(LoggerFactory.Create((builder) => builder.AddXUnit())), cache);
//When
mockLiveProductListingManager.RefreshProductListings();
//Then
Assert.True(cache.LastUpdatedUtc.Equals(mockLiveProductListingManager.LastDownload));
Assert.NotEmpty(await mockLiveProductListingManager.ProductListings);
}
}
}