Throttle episode scanning to 10 concurrent scans.

This commit is contained in:
Michael Bucari-Tovo 2022-05-25 20:43:12 -06:00
parent 76954b5a0a
commit a8f41841bd

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AudibleApi; using AudibleApi;
using AudibleApi.Common; using AudibleApi.Common;
@ -123,14 +124,15 @@ namespace AudibleUtilities
List<Task<List<Item>>> getChildEpisodesTasks = new(); List<Task<List<Item>>> getChildEpisodesTasks = new();
int count = 0; int count = 0, maxConcurrentEpisodeScans = 10;
using SemaphoreSlim concurrencySemaphore = new(maxConcurrentEpisodeScans);
await foreach (var item in Api.GetLibraryItemAsyncEnumerable(libraryOptions)) await foreach (var item in Api.GetLibraryItemAsyncEnumerable(libraryOptions))
{ {
if (item.IsEpisodes && importEpisodes) if (item.IsEpisodes && importEpisodes)
{ {
//Get child episodes asynchronously and await all at the end //Get child episodes asynchronously and await all at the end
getChildEpisodesTasks.Add(getChildEpisodesAsync(item)); getChildEpisodesTasks.Add(getChildEpisodesAsync(concurrencySemaphore, item));
} }
else if (!item.IsEpisodes) else if (!item.IsEpisodes)
items.Add(item); items.Add(item);
@ -138,7 +140,7 @@ namespace AudibleUtilities
count++; count++;
} }
Serilog.Log.Logger.Debug("Library scan complete. Found {count} books. Waiting on episode scans to complete", count); Serilog.Log.Logger.Debug("Library scan complete. Found {count} books and series. Waiting on {getChildEpisodesTasksCount} series episode scans to complete", count, getChildEpisodesTasks.Count);
//await and add all episides from all parents //await and add all episides from all parents
foreach (var epList in await Task.WhenAll(getChildEpisodesTasks)) foreach (var epList in await Task.WhenAll(getChildEpisodesTasks))
@ -163,24 +165,28 @@ namespace AudibleUtilities
#region episodes and podcasts #region episodes and podcasts
private async Task<List<Item>> getChildEpisodesAsync(Item parent) private async Task<List<Item>> getChildEpisodesAsync(SemaphoreSlim concurrencySemaphore, Item parent)
{ {
Serilog.Log.Logger.Debug("Beginning episode scan for {parent}", parent); await concurrencySemaphore.WaitAsync();
var children = await getEpisodeChildrenAsync(parent); try
// actual individual episode, not the parent of a series.
// for now I'm keeping it inside this method since it fits the work flow, incl. importEpisodes logic
if (!children.Any())
return new List<Item>() { parent };
foreach (var child in children)
{ {
// use parent's 'DateAdded'. DateAdded is just a convenience prop for: PurchaseDate.UtcDateTime Serilog.Log.Logger.Debug("Beginning episode scan for {parent}", parent);
child.PurchaseDate = parent.PurchaseDate;
// parent is essentially a series var children = await getEpisodeChildrenAsync(parent);
child.Series = new Series[]
// actual individual episode, not the parent of a series.
// for now I'm keeping it inside this method since it fits the work flow, incl. importEpisodes logic
if (!children.Any())
return new List<Item>() { parent };
foreach (var child in children)
{ {
// use parent's 'DateAdded'. DateAdded is just a convenience prop for: PurchaseDate.UtcDateTime
child.PurchaseDate = parent.PurchaseDate;
// parent is essentially a series
child.Series = new Series[]
{
new Series new Series
{ {
Asin = parent.Asin, Asin = parent.Asin,
@ -188,18 +194,23 @@ namespace AudibleUtilities
Sequence = parent.Relationships.FirstOrDefault(r => r.Asin == child.Asin).Sort.ToString(), Sequence = parent.Relationships.FirstOrDefault(r => r.Asin == child.Asin).Sort.ToString(),
Title = parent.TitleWithSubtitle Title = parent.TitleWithSubtitle
} }
}; };
// overload (read: abuse) IsEpisodes flag // overload (read: abuse) IsEpisodes flag
child.Relationships = new Relationship[] child.Relationships = new Relationship[]
{ {
new Relationship new Relationship
{ {
RelationshipToProduct = RelationshipToProduct.Child, RelationshipToProduct = RelationshipToProduct.Child,
RelationshipType = RelationshipType.Episode RelationshipType = RelationshipType.Episode
} }
}; };
}
return children;
}
finally
{
concurrencySemaphore.Release();
} }
return children;
} }
private async Task<List<Item>> getEpisodeChildrenAsync(Item parent) private async Task<List<Item>> getEpisodeChildrenAsync(Item parent)