Fixing media importer and adding importer robustness
ImportContext wasn't being set on the importers which caused problems during the import process. Fixed that and added a bunch more logging around the place so we can get better tracing into what's happening through the import pipeline
This commit is contained in:
parent
ef12bc58c9
commit
869b7ea466
4 changed files with 76 additions and 70 deletions
|
|
@ -7,7 +7,7 @@ public class ImportContextFactory(IServiceProvider serviceProvider)
|
|||
public ImportContext Create()
|
||||
{
|
||||
var scope = serviceProvider.CreateScope();
|
||||
|
||||
|
||||
return new ImportContext(scope.ServiceProvider);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,10 +6,10 @@ using Microsoft.Extensions.Logging;
|
|||
|
||||
namespace LANCommander.Launcher.Services.Import;
|
||||
|
||||
public class ImportContext
|
||||
public class ImportContext
|
||||
{
|
||||
public int Processed;
|
||||
public int Total;
|
||||
private int Processed;
|
||||
private int Total;
|
||||
|
||||
public AsyncEventHandler<ImportStatusUpdate> OnImportStarted { get; set; } = new();
|
||||
public AsyncEventHandler<ImportStatusUpdate> OnImportComplete { get; set; } = new();
|
||||
|
|
@ -18,7 +18,6 @@ public class ImportContext
|
|||
|
||||
private Queue<IImportItemInfo> Queue { get; } = new();
|
||||
|
||||
#region Importers
|
||||
private readonly CollectionImporter _collections;
|
||||
private readonly DeveloperImporter _developers;
|
||||
private readonly EngineImporter _engines;
|
||||
|
|
@ -28,27 +27,27 @@ public class ImportContext
|
|||
private readonly MultiplayerModeImporter _multiplayerModes;
|
||||
private readonly PlatformImporter _platforms;
|
||||
private readonly PublisherImporter _publishers;
|
||||
private readonly TagImporter _tags;
|
||||
#endregion
|
||||
|
||||
private readonly ILogger<ImportContext> _logger;
|
||||
|
||||
public ImportContext(IServiceProvider serviceProvider)
|
||||
{
|
||||
_collections = serviceProvider.GetRequiredService<CollectionImporter>();
|
||||
_developers = serviceProvider.GetRequiredService<DeveloperImporter>();
|
||||
_engines = serviceProvider.GetRequiredService<EngineImporter>();
|
||||
_games = serviceProvider.GetRequiredService<GameImporter>();
|
||||
_genres = serviceProvider.GetRequiredService<GenreImporter>();
|
||||
_media = serviceProvider.GetRequiredService<MediaImporter>();
|
||||
_multiplayerModes = serviceProvider.GetRequiredService<MultiplayerModeImporter>();
|
||||
_platforms = serviceProvider.GetRequiredService<PlatformImporter>();
|
||||
_publishers = serviceProvider.GetRequiredService<PublisherImporter>();
|
||||
_tags = serviceProvider.GetRequiredService<TagImporter>();
|
||||
|
||||
_logger = serviceProvider.GetRequiredService<ILogger<ImportContext>>();
|
||||
}
|
||||
|
||||
private readonly TagImporter _tags;
|
||||
|
||||
private readonly ILogger<ImportContext> _logger;
|
||||
|
||||
public ImportContext(IServiceProvider serviceProvider)
|
||||
{
|
||||
_collections = serviceProvider.GetRequiredService<CollectionImporter>();
|
||||
_developers = serviceProvider.GetRequiredService<DeveloperImporter>();
|
||||
_engines = serviceProvider.GetRequiredService<EngineImporter>();
|
||||
_games = serviceProvider.GetRequiredService<GameImporter>();
|
||||
_genres = serviceProvider.GetRequiredService<GenreImporter>();
|
||||
_media = serviceProvider.GetRequiredService<MediaImporter>();
|
||||
_multiplayerModes = serviceProvider.GetRequiredService<MultiplayerModeImporter>();
|
||||
_platforms = serviceProvider.GetRequiredService<PlatformImporter>();
|
||||
_publishers = serviceProvider.GetRequiredService<PublisherImporter>();
|
||||
_tags = serviceProvider.GetRequiredService<TagImporter>();
|
||||
_logger = serviceProvider.GetRequiredService<ILogger<ImportContext>>();
|
||||
|
||||
SetupContextOnImporters();
|
||||
}
|
||||
|
||||
public async Task AddAsync(Game game)
|
||||
{
|
||||
await AddAsync(game, game.Collections, _collections);
|
||||
|
|
@ -77,7 +76,9 @@ public class ImportContext
|
|||
{
|
||||
var importInfo = await importer.GetImportInfoAsync(record, manifest);
|
||||
|
||||
importInfo.Key = importer.GetKey(record);
|
||||
importInfo.Key = importer.GetKey(record);
|
||||
|
||||
_logger.LogInformation("Queuing item {ItemName} for import with key {Key}", importInfo.Name, importInfo.Key);
|
||||
|
||||
Queue.Enqueue(importInfo);
|
||||
}
|
||||
|
|
@ -102,6 +103,7 @@ public class ImportContext
|
|||
|
||||
while (Queue.Count > 0)
|
||||
{
|
||||
_logger.LogInformation("Importing item {Current} of {Total}", Processed + 1, Total);
|
||||
var queueItem = Queue.Dequeue();
|
||||
|
||||
await OnImportStatusUpdate?.InvokeAsync(new ImportStatusUpdate
|
||||
|
|
@ -115,11 +117,13 @@ public class ImportContext
|
|||
|
||||
if (success)
|
||||
{
|
||||
_logger.LogInformation("Successfully imported item {ItemName}", queueItem.Name);
|
||||
Processed++;
|
||||
deferred = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
_logger.LogInformation("Deferring item {ItemName} for later import", queueItem.Name);
|
||||
Queue.Enqueue(queueItem);
|
||||
deferred++;
|
||||
|
||||
|
|
@ -134,42 +138,38 @@ public class ImportContext
|
|||
})!;
|
||||
}
|
||||
|
||||
private void SetupContextOnImporters()
|
||||
{
|
||||
_collections.UseContext(this);
|
||||
_developers.UseContext(this);
|
||||
_engines.UseContext(this);
|
||||
_games.UseContext(this);
|
||||
_genres.UseContext(this);
|
||||
_media.UseContext(this);
|
||||
_multiplayerModes.UseContext(this);
|
||||
_platforms.UseContext(this);
|
||||
_publishers.UseContext(this);
|
||||
_tags.UseContext(this);
|
||||
}
|
||||
|
||||
private async Task<bool> TryImportAsync(IImportItemInfo queueItem)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (queueItem.Type)
|
||||
return queueItem.Type switch
|
||||
{
|
||||
case nameof(Collection):
|
||||
return await _collections.ImportAsync(queueItem);
|
||||
|
||||
case "Developer":
|
||||
return await _developers.ImportAsync(queueItem);
|
||||
|
||||
case nameof(Engine):
|
||||
return await _engines.ImportAsync(queueItem);
|
||||
|
||||
case nameof(Game):
|
||||
return await _games.ImportAsync(queueItem);
|
||||
|
||||
case nameof(Genre):
|
||||
return await _genres.ImportAsync(queueItem);
|
||||
|
||||
case nameof(Media):
|
||||
return await _media.ImportAsync(queueItem);
|
||||
|
||||
case nameof(MultiplayerMode):
|
||||
return await _multiplayerModes.ImportAsync(queueItem);
|
||||
|
||||
case nameof(Platform):
|
||||
return await _platforms.ImportAsync(queueItem);
|
||||
|
||||
case "Publisher":
|
||||
return await _publishers.ImportAsync(queueItem);
|
||||
|
||||
case nameof(Tag):
|
||||
return await _tags.ImportAsync(queueItem);
|
||||
}
|
||||
nameof(Collection) => await _collections.ImportAsync(queueItem),
|
||||
"Developer" => await _developers.ImportAsync(queueItem),
|
||||
nameof(Engine) => await _engines.ImportAsync(queueItem),
|
||||
nameof(Game) => await _games.ImportAsync(queueItem),
|
||||
nameof(Genre) => await _genres.ImportAsync(queueItem),
|
||||
nameof(Media) => await _media.ImportAsync(queueItem),
|
||||
nameof(MultiplayerMode) => await _multiplayerModes.ImportAsync(queueItem),
|
||||
nameof(Platform) => await _platforms.ImportAsync(queueItem),
|
||||
"Publisher" => await _publishers.ImportAsync(queueItem),
|
||||
nameof(Tag) => await _tags.ImportAsync(queueItem),
|
||||
_ => throw new InvalidOperationException($"No importer found for type {queueItem.Type}"),
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace LANCommander.Launcher.Services.Import.Importers;
|
|||
|
||||
public abstract class BaseImporter<TRecord> : IImporter<TRecord> where TRecord : class
|
||||
{
|
||||
protected ImportContext ImportContext { get; private set; }
|
||||
protected ImportContext? ImportContext { get; private set; }
|
||||
|
||||
public void UseContext(ImportContext importContext)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class MediaImporter(
|
|||
new()
|
||||
{
|
||||
Type = nameof(Media),
|
||||
Name = String.IsNullOrWhiteSpace(record.Name) ? record.Type.ToString() : $"{record.Type} - {record.Name}",
|
||||
Name = string.IsNullOrWhiteSpace(record.Name) ? record.Type.ToString() : $"{record.Type} - {record.Name}",
|
||||
Record = record,
|
||||
Manifest = manifest,
|
||||
};
|
||||
|
|
@ -35,11 +35,14 @@ public class MediaImporter(
|
|||
{
|
||||
try
|
||||
{
|
||||
var game = importItemInfo.Manifest as Game;
|
||||
|
||||
if (game == null)
|
||||
if (importItemInfo.Manifest is not Game game)
|
||||
return false;
|
||||
|
||||
if (ImportContext is null)
|
||||
{
|
||||
throw new InvalidOperationException("The ImportContext has not been set. Ensure that the UseContext method is called before importing.");
|
||||
}
|
||||
|
||||
if (ImportContext.InQueue(game, gameImporter))
|
||||
return false;
|
||||
|
||||
|
|
@ -53,7 +56,7 @@ public class MediaImporter(
|
|||
UpdatedOn = importItemInfo.Record.UpdatedOn,
|
||||
SourceUrl = importItemInfo.Record.SourceUrl,
|
||||
MimeType = importItemInfo.Record.MimeType,
|
||||
Crc32 = importItemInfo.Record.Crc32 ?? String.Empty,
|
||||
Crc32 = importItemInfo.Record.Crc32 ?? string.Empty,
|
||||
};
|
||||
|
||||
media = await mediaService.AddAsync(media);
|
||||
|
|
@ -62,6 +65,11 @@ public class MediaImporter(
|
|||
|
||||
return true;
|
||||
}
|
||||
catch(InvalidOperationException ex)
|
||||
{
|
||||
logger.LogError(ex, "Failed to add media due to invalid operation | {Key}", GetKey(importItemInfo.Record));
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Could not add media | {Key}", GetKey(importItemInfo.Record));
|
||||
|
|
@ -88,7 +96,7 @@ public class MediaImporter(
|
|||
existing.UpdatedOn = importItemInfo.Record.UpdatedOn;
|
||||
existing.SourceUrl = importItemInfo.Record.SourceUrl;
|
||||
existing.MimeType = importItemInfo.Record.MimeType;
|
||||
existing.Crc32 = importItemInfo.Record.Crc32 ?? String.Empty;
|
||||
existing.Crc32 = importItemInfo.Record.Crc32 ?? string.Empty;
|
||||
|
||||
await mediaService.UpdateAsync(existing);
|
||||
await mediaService.DownloadAsync(existing);
|
||||
|
|
@ -96,8 +104,6 @@ public class MediaImporter(
|
|||
return true;
|
||||
}
|
||||
|
||||
public override async Task<bool> ExistsAsync(ImportItemInfo<Media> importItemInfo)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public override async Task<bool> ExistsAsync(ImportItemInfo<Media> importItemInfo) =>
|
||||
await mediaService.FileExists(importItemInfo.Record.Id);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue