Skip to content

Commit

Permalink
#1833 refactor thumbnail Service into a factory
Browse files Browse the repository at this point in the history
  • Loading branch information
qdraw committed Jan 4, 2025
1 parent 977e14a commit 68c55ed
Show file tree
Hide file tree
Showing 69 changed files with 2,608 additions and 1,641 deletions.
125 changes: 63 additions & 62 deletions starsky/starsky.feature.export/Services/ExportService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,32 @@
using starsky.foundation.database.Interfaces;
using starsky.foundation.database.Models;
using starsky.foundation.injection;
using starsky.foundation.platform.Enums;
using starsky.foundation.platform.Helpers;
using starsky.foundation.platform.Interfaces;
using starsky.foundation.platform.Models;
using starsky.foundation.platform.Thumbnails;
using starsky.foundation.storage.ArchiveFormats;
using starsky.foundation.storage.Helpers;
using starsky.foundation.storage.Interfaces;
using starsky.foundation.storage.Models;
using starsky.foundation.storage.Storage;
using starsky.foundation.thumbnailgeneration.Interfaces;
using starsky.foundation.thumbnailgeneration.GenerationFactory.Interfaces;

[assembly: InternalsVisibleTo("starskytest")]

namespace starsky.feature.export.Services;

/// <summary>
/// Also known as Download
/// Also known as Download
/// </summary>
[Service(typeof(IExport), InjectionLifetime = InjectionLifetime.Scoped)]
public class ExportService : IExport
{
private readonly IQuery _query;
private readonly AppSettings _appSettings;
private readonly IStorage _iStorage;
private readonly IStorage _hostFileSystemStorage;
private readonly IStorage _iStorage;
private readonly IWebLogger _logger;
private readonly IQuery _query;
private readonly IThumbnailService _thumbnailService;

public ExportService(IQuery query, AppSettings appSettings,
Expand All @@ -52,7 +52,7 @@ public ExportService(IQuery query, AppSettings appSettings,
}

/// <summary>
/// Export preflight
/// Export preflight
/// </summary>
/// <param name="inputFilePaths">list of subPaths</param>
/// <param name="collections">is stack collections enabled</param>
Expand All @@ -78,7 +78,7 @@ public async Task<Tuple<string, List<FileIndexItem>>> PreflightAsync(
}

if ( _iStorage.IsFolderOrFile(detailView.FileIndexItem.FilePath) ==
FolderOrFileModel.FolderOrFileTypeList.Deleted )
FolderOrFileModel.FolderOrFileTypeList.Deleted )
{
StatusCodesHelper.ReturnExifStatusError(detailView.FileIndexItem,
FileIndexItem.ExifStatus.NotFoundSourceMissing,
Expand All @@ -102,15 +102,61 @@ public async Task<Tuple<string, List<FileIndexItem>>> PreflightAsync(
return new Tuple<string, List<FileIndexItem>>(zipHash, fileIndexResultsList);
}

/// <summary>
/// Based on the preflight create a Zip Export
/// </summary>
/// <param name="fileIndexResultsList">Result of Preflight</param>
/// <param name="thumbnail">isThumbnail?</param>
/// <param name="zipOutputFileName">filename of zip file (no extension)</param>
/// <returns>nothing</returns>
public async Task CreateZip(List<FileIndexItem> fileIndexResultsList, bool thumbnail,
string zipOutputFileName)
{
var filePaths = await CreateListToExport(fileIndexResultsList, thumbnail);
var fileNames = await FilePathToFileNameAsync(filePaths, thumbnail);

new Zipper(_logger).CreateZip(_appSettings.TempFolder, filePaths, fileNames,
zipOutputFileName);

// Write a single file to be sure that writing is ready
var doneFileFullPath = Path.Combine(_appSettings.TempFolder, zipOutputFileName) + ".done";
await _hostFileSystemStorage.WriteStreamAsync(StringToStreamHelper.StringToStream("OK"),
doneFileFullPath);
if ( _appSettings.IsVerbose() )
{
_logger.LogInformation("[CreateZip] Zip done: " + doneFileFullPath);
}
}

/// <summary>
/// Is Zip Ready?
/// </summary>
/// <param name="zipOutputFileName">fileName without extension</param>
/// <returns>null if status file is not found, true if done file exist</returns>
public Tuple<bool?, string?> StatusIsReady(string zipOutputFileName)
{
var sourceFullPath = Path.Combine(_appSettings.TempFolder, zipOutputFileName) + ".zip";
var doneFileFullPath = Path.Combine(_appSettings.TempFolder, zipOutputFileName) + ".done";

if ( !_hostFileSystemStorage.ExistFile(sourceFullPath) )
{
return new Tuple<bool?, string?>(null, null);
}

// Read a single file to be sure that writing is ready
return new Tuple<bool?, string?>(_hostFileSystemStorage.ExistFile(doneFileFullPath),
sourceFullPath);
}

private async Task AddFileIndexResultsListForDirectory(DetailView detailView,
List<FileIndexItem> fileIndexResultsList)
{
var allFilesInFolder =
await _query.GetAllRecursiveAsync(detailView
.FileIndexItem?.FilePath!);
foreach ( var item in
allFilesInFolder.Where(item =>
item.FilePath != null && _iStorage.ExistFile(item.FilePath)) )
allFilesInFolder.Where(item =>
item.FilePath != null && _iStorage.ExistFile(item.FilePath)) )
{
item.Status = FileIndexItem.ExifStatus.Ok;
fileIndexResultsList.Add(item);
Expand All @@ -137,32 +183,7 @@ private void AddCollectionBasedImages(DetailView detailView,
}

/// <summary>
/// Based on the preflight create a Zip Export
/// </summary>
/// <param name="fileIndexResultsList">Result of Preflight</param>
/// <param name="thumbnail">isThumbnail?</param>
/// <param name="zipOutputFileName">filename of zip file (no extension)</param>
/// <returns>nothing</returns>
public async Task CreateZip(List<FileIndexItem> fileIndexResultsList, bool thumbnail,
string zipOutputFileName)
{
var filePaths = await CreateListToExport(fileIndexResultsList, thumbnail);
var fileNames = await FilePathToFileNameAsync(filePaths, thumbnail);

new Zipper(_logger).CreateZip(_appSettings.TempFolder, filePaths, fileNames, zipOutputFileName);

// Write a single file to be sure that writing is ready
var doneFileFullPath = Path.Combine(_appSettings.TempFolder, zipOutputFileName) + ".done";
await _hostFileSystemStorage.WriteStreamAsync(StringToStreamHelper.StringToStream("OK"),
doneFileFullPath);
if ( _appSettings.IsVerbose() )
{
_logger.LogInformation("[CreateZip] Zip done: " + doneFileFullPath);
}
}

/// <summary>
/// This list will be included in the zip - Export is called Download in the UI
/// This list will be included in the zip - Export is called Download in the UI
/// </summary>
/// <param name="fileIndexResultsList">the items</param>
/// <param name="thumbnail">add the thumbnail or the source image</param>
Expand All @@ -173,15 +194,15 @@ public async Task<List<string>> CreateListToExport(List<FileIndexItem> fileIndex
var filePaths = new List<string>();

foreach ( var item in fileIndexResultsList.Where(p =>
p.Status == FileIndexItem.ExifStatus.Ok && p.FileHash != null).ToList() )
p.Status == FileIndexItem.ExifStatus.Ok && p.FileHash != null).ToList() )
{
if ( thumbnail )
{
var sourceThumb = Path.Combine(_appSettings.ThumbnailTempFolder,
ThumbnailNameHelper.Combine(item.FileHash!, ThumbnailSize.Large, true));

await _thumbnailService
.CreateThumbAsync(item.FilePath!, item.FileHash!, true);
.GenerateThumbnail(item.FilePath!, item.FileHash!, true);

filePaths.Add(sourceThumb);
continue;
Expand All @@ -199,9 +220,9 @@ await _thumbnailService

// when there is .xmp sidecar file (but only when file is a RAW file, ignored when for example jpeg)
if ( !ExtensionRolesHelper.IsExtensionForceXmp(item.FilePath) ||
!_iStorage.ExistFile(
ExtensionRolesHelper.ReplaceExtensionWithXmp(
item.FilePath)) )
!_iStorage.ExistFile(
ExtensionRolesHelper.ReplaceExtensionWithXmp(
item.FilePath)) )
{
continue;
}
Expand All @@ -222,7 +243,7 @@ await _thumbnailService
}

/// <summary>
/// Get the filename (in case of thumbnail the source image name)
/// Get the filename (in case of thumbnail the source image name)
/// </summary>
/// <param name="filePaths">the full file paths </param>
/// <param name="thumbnail">copy the thumbnail (true) or the source image (false)</param>
Expand Down Expand Up @@ -252,7 +273,7 @@ internal async Task<List<string>> FilePathToFileNameAsync(IEnumerable<string> fi
}

/// <summary>
/// to create a unique name of the zip using c# get hashcode
/// to create a unique name of the zip using c# get hashcode
/// </summary>
/// <param name="fileIndexResultsList">list of objects with fileHashes</param>
/// <returns>unique 'get hashcode' string</returns>
Expand All @@ -270,24 +291,4 @@ private static string GetName(IEnumerable<FileIndexItem> fileIndexResultsList)

return shortName;
}

/// <summary>
/// Is Zip Ready?
/// </summary>
/// <param name="zipOutputFileName">fileName without extension</param>
/// <returns>null if status file is not found, true if done file exist</returns>
public Tuple<bool?, string?> StatusIsReady(string zipOutputFileName)
{
var sourceFullPath = Path.Combine(_appSettings.TempFolder, zipOutputFileName) + ".zip";
var doneFileFullPath = Path.Combine(_appSettings.TempFolder, zipOutputFileName) + ".done";

if ( !_hostFileSystemStorage.ExistFile(sourceFullPath) )
{
return new Tuple<bool?, string?>(null, null);
}

// Read a single file to be sure that writing is ready
return new Tuple<bool?, string?>(_hostFileSystemStorage.ExistFile(doneFileFullPath),
sourceFullPath);
}
}
2 changes: 1 addition & 1 deletion starsky/starsky.feature.import/Services/Import.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
using starsky.foundation.database.Query;
using starsky.foundation.database.Thumbnails;
using starsky.foundation.injection;
using starsky.foundation.platform.Enums;
using starsky.foundation.platform.Extensions;
using starsky.foundation.platform.Helpers;
using starsky.foundation.platform.Interfaces;
using starsky.foundation.platform.Models;
using starsky.foundation.platform.Thumbnails;
using starsky.foundation.readmeta.Services;
using starsky.foundation.storage.Interfaces;
using starsky.foundation.storage.Models;
Expand Down
36 changes: 20 additions & 16 deletions starsky/starsky.feature.metaupdate/Services/MetaUpdateService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
using starsky.foundation.storage.Interfaces;
using starsky.foundation.storage.Services;
using starsky.foundation.storage.Storage;
using starsky.foundation.thumbnailgeneration.Interfaces;
using starsky.foundation.thumbnailgeneration.GenerationFactory.Interfaces;
using starsky.foundation.writemeta.Interfaces;
using starsky.foundation.writemeta.JsonService;
using ExifToolCmdHelper = starsky.foundation.writemeta.Helpers.ExifToolCmdHelper;
Expand All @@ -27,15 +27,15 @@ namespace starsky.feature.metaupdate.Services;
[Service(typeof(IMetaUpdateService), InjectionLifetime = InjectionLifetime.Scoped)]
public class MetaUpdateService : IMetaUpdateService
{
private readonly IQuery _query;
private readonly IExifTool _exifTool;
private readonly IReadMetaSubPathStorage _readMeta;
private readonly IStorage _iStorage;
private readonly IStorage _thumbnailStorage;
private readonly IMetaPreflight _metaPreflight;
private readonly IWebLogger _logger;
private readonly IThumbnailService _thumbnailService;
private readonly IMetaPreflight _metaPreflight;
private readonly IQuery _query;
private readonly IReadMetaSubPathStorage _readMeta;
private readonly IThumbnailQuery _thumbnailQuery;
private readonly IThumbnailService _thumbnailService;
private readonly IStorage _thumbnailStorage;

[SuppressMessage("Usage",
"S107: Constructor has 8 parameters, which is greater than the 7 authorized")]
Expand All @@ -61,13 +61,17 @@ public MetaUpdateService(
}

/// <summary>
/// Run Update
/// Run Update
/// </summary>
/// <param name="changedFileIndexItemName">Per file stored string{fileHash},
/// List*string*{FileIndexItem.name (e.g. Tags) that are changed}</param>
/// <param name="changedFileIndexItemName">
/// Per file stored string{fileHash},
/// List*string*{FileIndexItem.name (e.g. Tags) that are changed}
/// </param>
/// <param name="fileIndexResultsList">items stored in the database</param>
/// <param name="inputModel">(only used when cache is disabled)
/// This model is overwritten in the database and ExifTool</param>
/// <param name="inputModel">
/// (only used when cache is disabled)
/// This model is overwritten in the database and ExifTool
/// </param>
/// <param name="collections">enable or disable this feature</param>
/// <param name="append">only for disabled cache or changedFileIndexItemName=null</param>
/// <param name="rotateClock">rotation value 1 left, -1 right, 0 nothing</param>
Expand Down Expand Up @@ -103,7 +107,7 @@ public async Task<List<FileIndexItem>> UpdateAsync(

_logger.LogError($"Missing in key: {fileIndexItem.FilePath}",
new InvalidDataException($"changedFileIndexItemName: " +
$"{string.Join(",", changedFileIndexItemName)}"));
$"{string.Join(",", changedFileIndexItemName)}"));
throw new ArgumentException($"Missing in key: {fileIndexItem.FilePath}",
nameof(changedFileIndexItemName));
}
Expand All @@ -117,7 +121,7 @@ public void UpdateReadMetaCache(IEnumerable<FileIndexItem> returnNewResultList)
}

/// <summary>
/// Update ExifTool, Thumbnail, Database and if needed rotateClock
/// Update ExifTool, Thumbnail, Database and if needed rotateClock
/// </summary>
/// <param name="fileIndexItem">output database object</param>
/// <param name="comparedNamesList">name of fields updated by exifTool</param>
Expand All @@ -129,7 +133,7 @@ private async Task UpdateWriteDiskDatabase(FileIndexItem fileIndexItem,
await RotationThumbnailExecute(rotateClock, fileIndexItem);

if ( fileIndexItem.IsDirectory != true
&& ExtensionRolesHelper.IsExtensionExifToolSupported(fileIndexItem.FileName) )
&& ExtensionRolesHelper.IsExtensionExifToolSupported(fileIndexItem.FileName) )
{
// feature to exif update
var exifUpdateFilePaths = new List<string> { fileIndexItem.FilePath! };
Expand All @@ -152,7 +156,7 @@ private async Task UpdateWriteDiskDatabase(FileIndexItem fileIndexItem,
: $"[UpdateWriteDiskDatabase] ExifTool result: {exifResult} path:{fileIndexItem.FilePath}");
}
else if ( fileIndexItem.ImageFormat != ExtensionRolesHelper.ImageFormat.xmp &&
fileIndexItem.ImageFormat != ExtensionRolesHelper.ImageFormat.meta_json )
fileIndexItem.ImageFormat != ExtensionRolesHelper.ImageFormat.meta_json )
{
await new FileIndexItemJsonParser(_iStorage).WriteAsync(fileIndexItem);
}
Expand Down Expand Up @@ -192,7 +196,7 @@ internal async Task ApplyOrGenerateUpdatedFileHash(List<string> newFileHashes,
}

/// <summary>
/// Run the Orientation changes on the thumbnail (only relative)
/// Run the Orientation changes on the thumbnail (only relative)
/// </summary>
/// <param name="rotateClock">-1 or 1</param>
/// <param name="fileIndexItem">object contains fileHash</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using starsky.foundation.platform.Interfaces;
using starsky.foundation.platform.Models;
using starsky.foundation.realtime.Interfaces;
using starsky.foundation.thumbnailgeneration.GenerationFactory.Interfaces;
using starsky.foundation.thumbnailgeneration.Interfaces;
using starsky.foundation.worker.ThumbnailServices.Interfaces;

Expand Down Expand Up @@ -122,7 +123,7 @@ internal async Task<IEnumerable<ThumbnailItem>> WorkThumbnailGeneration(
}

var generationResultModels = (
await _thumbnailService.CreateThumbAsync(fileIndexItem
await _thumbnailService.GenerateThumbnail(fileIndexItem
.FilePath!, fileIndexItem.FileHash!) ).ToList();

_bgTaskQueue.ThrowExceptionIfCpuUsageIsToHigh("WorkThumbnailGeneration");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
using starsky.foundation.platform.Interfaces;
using starsky.foundation.platform.Models;
using starsky.foundation.realtime.Interfaces;
using starsky.foundation.thumbnailgeneration.Interfaces;
using starsky.foundation.thumbnailgeneration.GenerationFactory.Interfaces;
using starsky.foundation.thumbnailgeneration.Models;
using starsky.foundation.worker.ThumbnailServices.Interfaces;

Expand Down Expand Up @@ -54,7 +54,7 @@ internal async Task WorkThumbnailGeneration(string subPath)
try
{
_logger.LogInformation($"[ThumbnailGenerationController] start {subPath}");
var thumbs = await _thumbnailService.CreateThumbnailAsync(subPath);
var thumbs = await _thumbnailService.GenerateThumbnail(subPath);
var getAllFilesAsync = await _query.GetAllFilesAsync(subPath);

var result =
Expand Down
Loading

0 comments on commit 68c55ed

Please sign in to comment.