Merge p1-w2-ta-content-models: design majors Content.Services + Models
This commit is contained in:
@@ -10,4 +10,8 @@
|
|||||||
<ProjectReference Include="..\DeepDrftModels\DeepDrftModels.csproj" />
|
<ProjectReference Include="..\DeepDrftModels\DeepDrftModels.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -3,12 +3,20 @@ using DeepDrftContent.Services.FileDatabase.Services;
|
|||||||
|
|
||||||
namespace DeepDrftContent.Services.FileDatabase.Models;
|
namespace DeepDrftContent.Services.FileDatabase.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shared media type registry instance — one allocation for all factory classes in this file.
|
||||||
|
/// </summary>
|
||||||
|
file static class SharedMediaTypeRegistry
|
||||||
|
{
|
||||||
|
internal static readonly IMediaTypeRegistry Instance = new SimpleMediaTypeRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type mappings for media vault types - simple dictionary-based approach
|
/// Type mappings for media vault types - simple dictionary-based approach
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class MediaVaultTypeMap
|
public static class MediaVaultTypeMap
|
||||||
{
|
{
|
||||||
private static readonly IMediaTypeRegistry _registry = new SimpleMediaTypeRegistry();
|
private static readonly IMediaTypeRegistry _registry = SharedMediaTypeRegistry.Instance;
|
||||||
|
|
||||||
public static Type GetBinaryType(MediaVaultType vaultType) => _registry.GetBinaryType(vaultType);
|
public static Type GetBinaryType(MediaVaultType vaultType) => _registry.GetBinaryType(vaultType);
|
||||||
|
|
||||||
@@ -55,7 +63,7 @@ public static class MetaDataFactory
|
|||||||
return new AudioMetaData(entryKey, extension, duration, bitrate);
|
return new AudioMetaData(entryKey, extension, duration, bitrate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly IMediaTypeRegistry _metaDataRegistry = new SimpleMediaTypeRegistry();
|
private static readonly IMediaTypeRegistry _metaDataRegistry = SharedMediaTypeRegistry.Instance;
|
||||||
|
|
||||||
public static MetaData CreateFromMedia(MediaVaultType type, string entryKey, string extension, object media)
|
public static MetaData CreateFromMedia(MediaVaultType type, string entryKey, string extension, object media)
|
||||||
{
|
{
|
||||||
@@ -75,7 +83,7 @@ public static class MetaDataFactory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class MediaParamsFactory
|
public static class MediaParamsFactory
|
||||||
{
|
{
|
||||||
private static readonly IMediaTypeRegistry _registry = new SimpleMediaTypeRegistry();
|
private static readonly IMediaTypeRegistry _registry = SharedMediaTypeRegistry.Instance;
|
||||||
|
|
||||||
public static object Create(MediaVaultType type, FileBinary fileBinary, MetaData metaData)
|
public static object Create(MediaVaultType type, FileBinary fileBinary, MetaData metaData)
|
||||||
{
|
{
|
||||||
@@ -94,7 +102,7 @@ public static class MediaParamsFactory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class FileBinaryFactory
|
public static class FileBinaryFactory
|
||||||
{
|
{
|
||||||
private static readonly IMediaTypeRegistry _registry = new SimpleMediaTypeRegistry();
|
private static readonly IMediaTypeRegistry _registry = SharedMediaTypeRegistry.Instance;
|
||||||
|
|
||||||
public static object Create(MediaVaultType vaultType, object parameters)
|
public static object Create(MediaVaultType vaultType, object parameters)
|
||||||
{
|
{
|
||||||
@@ -124,7 +132,7 @@ public static class FileBinaryFactory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class FileBinaryDtoFactory
|
public static class FileBinaryDtoFactory
|
||||||
{
|
{
|
||||||
private static readonly IMediaTypeRegistry _registry = new SimpleMediaTypeRegistry();
|
private static readonly IMediaTypeRegistry _registry = SharedMediaTypeRegistry.Instance;
|
||||||
|
|
||||||
public static object From(MediaVaultType type, object mediaBinary)
|
public static object From(MediaVaultType type, object mediaBinary)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class MediaBinary : FileBinary
|
|||||||
return new MediaBinary(new MediaBinaryParams(buffer, dto.Size, extension));
|
return new MediaBinary(new MediaBinaryParams(buffer, dto.Size, extension));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetExtensionType(string mime)
|
protected static string GetExtensionType(string mime)
|
||||||
{
|
{
|
||||||
return MimeTypeExtensions.GetExtension(mime);
|
return MimeTypeExtensions.GetExtension(mime);
|
||||||
}
|
}
|
||||||
@@ -116,11 +116,6 @@ public class ImageBinary : MediaBinary
|
|||||||
var extension = GetExtensionType(dto.Mime);
|
var extension = GetExtensionType(dto.Mime);
|
||||||
return new ImageBinary(new ImageBinaryParams(buffer, dto.Size, extension, dto.AspectRatio));
|
return new ImageBinary(new ImageBinaryParams(buffer, dto.Size, extension, dto.AspectRatio));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetExtensionType(string mime)
|
|
||||||
{
|
|
||||||
return MimeTypeExtensions.GetExtension(mime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -171,11 +166,6 @@ public class AudioBinary : MediaBinary
|
|||||||
var extension = GetExtensionType(dto.Mime);
|
var extension = GetExtensionType(dto.Mime);
|
||||||
return new AudioBinary(new AudioBinaryParams(buffer, dto.Size, extension, dto.Duration, dto.Bitrate));
|
return new AudioBinary(new AudioBinaryParams(buffer, dto.Size, extension, dto.Duration, dto.Bitrate));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetExtensionType(string mime)
|
|
||||||
{
|
|
||||||
return MimeTypeExtensions.GetExtension(mime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
|
|||||||
{
|
{
|
||||||
private readonly StructuralMap<string, MediaVault> _vaults;
|
private readonly StructuralMap<string, MediaVault> _vaults;
|
||||||
private readonly IndexWatcher _indexWatcher;
|
private readonly IndexWatcher _indexWatcher;
|
||||||
|
private readonly IndexFactoryService _indexFactory;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -23,7 +24,7 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
|
|||||||
|
|
||||||
if (rootIndex != null)
|
if (rootIndex != null)
|
||||||
{
|
{
|
||||||
var db = new FileDatabase(rootPath, rootIndex);
|
var db = new FileDatabase(rootPath, rootIndex, factoryService);
|
||||||
await db.InitVaultsAsync();
|
await db.InitVaultsAsync();
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
@@ -31,10 +32,11 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileDatabase(string rootPath, IDirectoryIndex index) : base(rootPath, index)
|
private FileDatabase(string rootPath, IDirectoryIndex index, IndexFactoryService indexFactory) : base(rootPath, index)
|
||||||
{
|
{
|
||||||
_vaults = new StructuralMap<string, MediaVault>();
|
_vaults = new StructuralMap<string, MediaVault>();
|
||||||
_indexWatcher = new IndexWatcher();
|
_indexWatcher = new IndexWatcher();
|
||||||
|
_indexFactory = indexFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -58,7 +60,7 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
|
|||||||
private async Task InitVaultAsync(string vaultId, MediaVaultType vaultType)
|
private async Task InitVaultAsync(string vaultId, MediaVaultType vaultType)
|
||||||
{
|
{
|
||||||
var path = Path.Combine(RootPath, vaultId);
|
var path = Path.Combine(RootPath, vaultId);
|
||||||
var directoryVault = await MediaVaultFactory.From(path, vaultType);
|
var directoryVault = await MediaVaultFactory.From(path, vaultType, _indexFactory);
|
||||||
|
|
||||||
if (directoryVault != null)
|
if (directoryVault != null)
|
||||||
{
|
{
|
||||||
@@ -80,9 +82,8 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var factoryService = new IndexFactoryService();
|
|
||||||
var vaultPath = Path.Combine(RootPath, vaultId);
|
var vaultPath = Path.Combine(RootPath, vaultId);
|
||||||
var index = await factoryService.LoadIndexAsync(IndexType.Vault, vaultPath);
|
var index = await _indexFactory.LoadIndexAsync(IndexType.Vault, vaultPath);
|
||||||
|
|
||||||
if (index is VaultIndex vaultIndex)
|
if (index is VaultIndex vaultIndex)
|
||||||
{
|
{
|
||||||
@@ -115,25 +116,18 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new vault
|
/// Creates a new vault. Propagates exceptions to the caller — vault creation failure is not
|
||||||
|
/// silently swallowable because a partially-created vault would leave the index inconsistent.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task CreateVaultAsync(string vaultId, MediaVaultType vaultType)
|
public async Task CreateVaultAsync(string vaultId, MediaVaultType vaultType)
|
||||||
{
|
{
|
||||||
try
|
var path = Path.Combine(RootPath, vaultId);
|
||||||
{
|
var directoryVault = await MediaVaultFactory.From(path, vaultType, _indexFactory);
|
||||||
var path = Path.Combine(RootPath, vaultId);
|
|
||||||
var directoryVault = await MediaVaultFactory.From(path, vaultType);
|
|
||||||
|
|
||||||
if (directoryVault != null)
|
if (directoryVault != null)
|
||||||
{
|
|
||||||
_vaults.Set(vaultId, directoryVault);
|
|
||||||
// Now using string-based index
|
|
||||||
await AddToIndexAsync(vaultId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
{
|
||||||
throw;
|
_vaults.Set(vaultId, directoryVault);
|
||||||
|
await AddToIndexAsync(vaultId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using DeepDrftContent.Services.FileDatabase.Abstractions;
|
using DeepDrftContent.Services.FileDatabase.Abstractions;
|
||||||
using DeepDrftContent.Services.FileDatabase.Models;
|
using DeepDrftContent.Services.FileDatabase.Models;
|
||||||
using DeepDrftContent.Services.FileDatabase.Utils;
|
using DeepDrftContent.Services.FileDatabase.Utils;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace DeepDrftContent.Services.FileDatabase.Services;
|
namespace DeepDrftContent.Services.FileDatabase.Services;
|
||||||
|
|
||||||
@@ -96,12 +97,15 @@ public class VaultIndexDirectory : IndexDirectory
|
|||||||
{
|
{
|
||||||
private IVaultIndex _vaultIndex;
|
private IVaultIndex _vaultIndex;
|
||||||
private readonly SemaphoreSlim _indexLock = new(1, 1);
|
private readonly SemaphoreSlim _indexLock = new(1, 1);
|
||||||
private readonly IndexFactoryService _factoryService = new();
|
private readonly IndexFactoryService _factoryService;
|
||||||
|
private readonly ILogger<VaultIndexDirectory>? _logger;
|
||||||
|
|
||||||
public VaultIndexDirectory(string rootPath, IVaultIndex index, IIndexDataFactory? indexDataFactory = null)
|
public VaultIndexDirectory(string rootPath, IVaultIndex index, IIndexDataFactory? indexDataFactory = null, ILogger<VaultIndexDirectory>? logger = null, IndexFactoryService? factoryService = null)
|
||||||
: base(rootPath, IndexType.Vault, index, indexDataFactory)
|
: base(rootPath, IndexType.Vault, index, indexDataFactory ?? factoryService)
|
||||||
{
|
{
|
||||||
_vaultIndex = index;
|
_vaultIndex = index;
|
||||||
|
_logger = logger;
|
||||||
|
_factoryService = factoryService ?? new IndexFactoryService();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task AddToIndexAsync(string entryId, MetaData metaData)
|
protected async Task AddToIndexAsync(string entryId, MetaData metaData)
|
||||||
@@ -131,12 +135,18 @@ public class VaultIndexDirectory : IndexDirectory
|
|||||||
{
|
{
|
||||||
_vaultIndex = vaultIndex;
|
_vaultIndex = vaultIndex;
|
||||||
Index = vaultIndex;
|
Index = vaultIndex;
|
||||||
Console.WriteLine($"VaultIndexDirectory: Reloaded index for {RootPath}, {vaultIndex.GetEntriesSize()} entries");
|
if (_logger != null)
|
||||||
|
_logger.LogDebug("VaultIndexDirectory: Reloaded index for {RootPath}, {EntryCount} entries", RootPath, vaultIndex.GetEntriesSize());
|
||||||
|
else
|
||||||
|
Console.WriteLine($"VaultIndexDirectory: Reloaded index for {RootPath}, {vaultIndex.GetEntriesSize()} entries");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"VaultIndexDirectory: Failed to reload index for {RootPath}: {ex.Message}");
|
if (_logger != null)
|
||||||
|
_logger.LogWarning(ex, "VaultIndexDirectory: Failed to reload index for {RootPath}", RootPath);
|
||||||
|
else
|
||||||
|
Console.WriteLine($"VaultIndexDirectory: Failed to reload index for {RootPath}: {ex.Message}");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using DeepDrftContent.Services.FileDatabase.Models;
|
using DeepDrftContent.Services.FileDatabase.Models;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace DeepDrftContent.Services.FileDatabase.Services;
|
namespace DeepDrftContent.Services.FileDatabase.Services;
|
||||||
|
|
||||||
@@ -11,8 +12,14 @@ public class IndexWatcher : IDisposable
|
|||||||
private readonly Dictionary<string, FileSystemWatcher> _watchers = new();
|
private readonly Dictionary<string, FileSystemWatcher> _watchers = new();
|
||||||
private readonly Dictionary<string, Action> _reloadCallbacks = new();
|
private readonly Dictionary<string, Action> _reloadCallbacks = new();
|
||||||
private readonly object _lock = new();
|
private readonly object _lock = new();
|
||||||
|
private readonly ILogger<IndexWatcher>? _logger;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
|
public IndexWatcher(ILogger<IndexWatcher>? logger = null)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers an index file to be watched for changes.
|
/// Registers an index file to be watched for changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -46,11 +53,17 @@ public class IndexWatcher : IDisposable
|
|||||||
_watchers[indexPath] = watcher;
|
_watchers[indexPath] = watcher;
|
||||||
_reloadCallbacks[indexPath] = onChanged;
|
_reloadCallbacks[indexPath] = onChanged;
|
||||||
|
|
||||||
Console.WriteLine($"IndexWatcher: Watching {indexPath}/index");
|
if (_logger != null)
|
||||||
|
_logger.LogDebug("IndexWatcher: Watching {IndexPath}/index", indexPath);
|
||||||
|
else
|
||||||
|
Console.WriteLine($"IndexWatcher: Watching {indexPath}/index");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"IndexWatcher: Failed to watch {indexPath}: {ex.Message}");
|
if (_logger != null)
|
||||||
|
_logger.LogWarning(ex, "IndexWatcher: Failed to watch {IndexPath}", indexPath);
|
||||||
|
else
|
||||||
|
Console.WriteLine($"IndexWatcher: Failed to watch {indexPath}: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +96,10 @@ public class IndexWatcher : IDisposable
|
|||||||
{
|
{
|
||||||
if (_reloadCallbacks.TryGetValue(indexPath, out var callback))
|
if (_reloadCallbacks.TryGetValue(indexPath, out var callback))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"IndexWatcher: Index changed at {indexPath}, triggering reload");
|
if (_logger != null)
|
||||||
|
_logger.LogDebug("IndexWatcher: Index changed at {IndexPath}, triggering reload", indexPath);
|
||||||
|
else
|
||||||
|
Console.WriteLine($"IndexWatcher: Index changed at {indexPath}, triggering reload");
|
||||||
|
|
||||||
// Invoke callback on a background thread to avoid blocking the watcher
|
// Invoke callback on a background thread to avoid blocking the watcher
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
@@ -94,7 +110,10 @@ public class IndexWatcher : IDisposable
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"IndexWatcher: Reload callback failed: {ex.Message}");
|
if (_logger != null)
|
||||||
|
_logger.LogWarning(ex, "IndexWatcher: Reload callback failed for {IndexPath}", indexPath);
|
||||||
|
else
|
||||||
|
Console.WriteLine($"IndexWatcher: Reload callback failed: {ex.Message}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ namespace DeepDrftContent.Services.FileDatabase.Services;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class MediaVault : VaultIndexDirectory
|
public abstract class MediaVault : VaultIndexDirectory
|
||||||
{
|
{
|
||||||
protected MediaVault(string rootPath, VaultIndex index) : base(rootPath, index) { }
|
protected MediaVault(string rootPath, VaultIndex index, IndexFactoryService? factoryService = null)
|
||||||
|
: base(rootPath, index, factoryService: factoryService) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a media key from an entry key by sanitizing special characters
|
/// Generates a media key from an entry key by sanitizing special characters
|
||||||
@@ -105,19 +106,20 @@ public abstract class MediaVault : VaultIndexDirectory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ImageVault : MediaVault
|
public class ImageVault : MediaVault
|
||||||
{
|
{
|
||||||
private ImageVault(string rootPath, VaultIndex index) : base(rootPath, index) { }
|
private ImageVault(string rootPath, VaultIndex index, IndexFactoryService? factoryService = null)
|
||||||
|
: base(rootPath, index, factoryService) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Factory method to create an ImageVault instance
|
/// Factory method to create an ImageVault instance
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static async Task<ImageVault?> FromAsync(string rootPath)
|
public static async Task<ImageVault?> FromAsync(string rootPath, IndexFactoryService? factoryService = null)
|
||||||
{
|
{
|
||||||
var factoryService = new IndexFactoryService();
|
var factory = factoryService ?? new IndexFactoryService();
|
||||||
var index = await factoryService.LoadOrCreateVaultIndexAsync(rootPath, MediaVaultType.Image);
|
var index = await factory.LoadOrCreateVaultIndexAsync(rootPath, MediaVaultType.Image);
|
||||||
|
|
||||||
if (index != null)
|
if (index != null)
|
||||||
{
|
{
|
||||||
return new ImageVault(rootPath, (VaultIndex)index);
|
return new ImageVault(rootPath, (VaultIndex)index, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -126,16 +128,17 @@ public class ImageVault : MediaVault
|
|||||||
|
|
||||||
public class AudioVault : MediaVault
|
public class AudioVault : MediaVault
|
||||||
{
|
{
|
||||||
private AudioVault(string rootPath, VaultIndex index) : base(rootPath, index) { }
|
private AudioVault(string rootPath, VaultIndex index, IndexFactoryService? factoryService = null)
|
||||||
|
: base(rootPath, index, factoryService) { }
|
||||||
public static async Task<AudioVault?> FromAsync(string rootPath)
|
|
||||||
|
public static async Task<AudioVault?> FromAsync(string rootPath, IndexFactoryService? factoryService = null)
|
||||||
{
|
{
|
||||||
var factoryService = new IndexFactoryService();
|
var factory = factoryService ?? new IndexFactoryService();
|
||||||
var index = await factoryService.LoadOrCreateVaultIndexAsync(rootPath, MediaVaultType.Audio);
|
var index = await factory.LoadOrCreateVaultIndexAsync(rootPath, MediaVaultType.Audio);
|
||||||
|
|
||||||
if (index != null)
|
if (index != null)
|
||||||
{
|
{
|
||||||
return new AudioVault(rootPath, (VaultIndex)index);
|
return new AudioVault(rootPath, (VaultIndex)index, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using DeepDrftContent.Services.FileDatabase.Abstractions;
|
using DeepDrftContent.Services.FileDatabase.Models;
|
||||||
using DeepDrftContent.Services.FileDatabase.Models;
|
|
||||||
|
|
||||||
namespace DeepDrftContent.Services.FileDatabase.Services;
|
namespace DeepDrftContent.Services.FileDatabase.Services;
|
||||||
|
|
||||||
@@ -8,10 +7,13 @@ namespace DeepDrftContent.Services.FileDatabase.Services;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class MediaVaultFactory
|
public static class MediaVaultFactory
|
||||||
{
|
{
|
||||||
private static readonly IMediaTypeRegistry _registry = new SimpleMediaTypeRegistry();
|
public static async Task<MediaVault?> From(string rootPath, MediaVaultType mediaType, IndexFactoryService? factoryService = null)
|
||||||
|
|
||||||
public static async Task<MediaVault?> From(string rootPath, MediaVaultType mediaType)
|
|
||||||
{
|
{
|
||||||
return await _registry.CreateVaultAsync(mediaType, rootPath);
|
return mediaType switch
|
||||||
|
{
|
||||||
|
MediaVaultType.Image => await ImageVault.FromAsync(rootPath, factoryService),
|
||||||
|
MediaVaultType.Audio => await AudioVault.FromAsync(rootPath, factoryService),
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,9 +75,10 @@ public class TrackService
|
|||||||
|
|
||||||
return trackEntity;
|
return trackEntity;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex) when (ex is not OperationCanceledException)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Failed to add track: {ex.Message}", ex);
|
Console.WriteLine($"TrackService.AddTrackFromWavAsync failed: {ex.Message}");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ public class TrackDto
|
|||||||
{
|
{
|
||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
public required string EntryKey { get; set; }
|
public required string EntryKey { get; set; }
|
||||||
public string TrackName { get; set; }
|
public required string TrackName { get; set; }
|
||||||
public string Artist { get; set; }
|
public required string Artist { get; set; }
|
||||||
public string? Album { get; set; }
|
public string? Album { get; set; }
|
||||||
public string? Genre { get; set; }
|
public string? Genre { get; set; }
|
||||||
public DateOnly? ReleaseDate { get; set; }
|
public DateOnly? ReleaseDate { get; set; }
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public class PagedResult<T>
|
|||||||
public int TotalCount { get; set; }
|
public int TotalCount { get; set; }
|
||||||
public int Page { get; set; }
|
public int Page { get; set; }
|
||||||
public int PageSize { get; set; }
|
public int PageSize { get; set; }
|
||||||
public int TotalPages => (int)Math.Ceiling((double)TotalCount / PageSize);
|
public int TotalPages => PageSize > 0 ? (int)Math.Ceiling((double)TotalCount / PageSize) : 0;
|
||||||
public bool HasNextPage => Page < TotalPages;
|
public bool HasNextPage => Page < TotalPages;
|
||||||
public bool HasPreviousPage => Page > 1;
|
public bool HasPreviousPage => Page > 1;
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ public class PagedResult<T>
|
|||||||
|
|
||||||
public PagedResult(IEnumerable<T> items, int totalCount, int page, int pageSize)
|
public PagedResult(IEnumerable<T> items, int totalCount, int page, int pageSize)
|
||||||
{
|
{
|
||||||
Items = items.ToList() ?? new List<T>();
|
Items = items.ToList();
|
||||||
TotalCount = totalCount;
|
TotalCount = totalCount;
|
||||||
Page = page;
|
Page = page;
|
||||||
PageSize = pageSize;
|
PageSize = pageSize;
|
||||||
|
|||||||
Reference in New Issue
Block a user