Renames and changes

This commit is contained in:
2026-03-28 15:32:36 +01:00
parent 3132b139f7
commit 7709fe737f
28 changed files with 236 additions and 241 deletions
@@ -4,19 +4,19 @@ namespace Musify.Application.Contracts.Infrastructure
{ {
public interface IStorageHandler public interface IStorageHandler
{ {
Task<Result<Stream>> GetFileAsync(string bucketName, string keyName, CancellationToken cancellationToken); Task<Result<Stream>> GetFileAsync(string bucket, string key, CancellationToken cancellationToken);
Task<string> GetUrlAsync(string bucketName, string keyName, TimeSpan ExpirationTime, CancellationToken cancellationToken); Task<string> GetUrlAsync(string bucket, string key, TimeSpan ExpirationTime, CancellationToken cancellationToken);
Task<Result<string>> UploadFileAsync(string filePath, string bucketName, string keyName, CancellationToken cancellationToken); Task<Result<string>> UploadFileAsync(string filePath, string bucket, string key, CancellationToken cancellationToken);
Task<Result<string>> UploadFileAsync(Stream sourceStream, string contentType, string bucketName, string keyName, CancellationToken cancellationToken); Task<Result<string>> UploadFileAsync(Stream sourceStream, string contentType, string bucket, string key, CancellationToken cancellationToken);
Task<Result> TransferFilesAsync(string sourceDirectory, string bucketName, string route, CancellationToken cancellationToken); Task<Result> TransferFilesAsync(string sourceDirectory, string bucket, string route, CancellationToken cancellationToken);
Task<Result> RemoveFileAsync(string bucketName, string keyName, CancellationToken cancellationToken); Task<Result> RemoveFileAsync(string bucket, string key, CancellationToken cancellationToken);
Task<Result> CopyFileAsync(string sourceBucketName, string sourceKeyName, string destinationBucketName, string destinationKeyName, Task<Result> CopyFileAsync(string sourceBucket, string sourceKey, string destinationBucket, string destinationKey,
CancellationToken cancellationToken); CancellationToken cancellationToken);
} }
} }
@@ -32,10 +32,10 @@ namespace Musify.Application.PlayLists.Handlers
Name = request.Name, Name = request.Name,
NormalizedName = request.Name.Trim().ToUpperInvariant(), NormalizedName = request.Name.Trim().ToUpperInvariant(),
Description = request.Description, Description = request.Description,
OriginalPictureKeyName = playListConfiguration.Routes.PresetOriginalPicture, OriginalPictureName = playListConfiguration.Routes.PresetOriginalPicture,
SmallPictureKeyName = playListConfiguration.Routes.PresetSmallPicture, SmallPictureName = playListConfiguration.Routes.PresetSmallPicture,
MediumPictureKeyName = playListConfiguration.Routes.PresetMediumPicture, MediumPictureName = playListConfiguration.Routes.PresetMediumPicture,
LargePictureKeyName = playListConfiguration.Routes.PresetLargePicture, LargePictureName = playListConfiguration.Routes.PresetLargePicture,
}; };
var setPictureResult = request.Picture is null var setPictureResult = request.Picture is null
@@ -63,12 +63,12 @@ namespace Musify.Application.PlayLists.Handlers
if (!uploadResult.IsSuccess) if (!uploadResult.IsSuccess)
{ {
logger.LogError("Failed to upload picture for PlayList with Id={PlayListId} to storage. Storage handler returned error: {ErrorMessage}", logger.LogError("Failed to upload picture for PlayList with Id={PlayListId} to storage. Storage handler returned error={ErrorMessage}",
playList.Id, string.Join("; ", uploadResult.Errors)); playList.Id, string.Join("; ", uploadResult.Errors));
return Result.Error($"Failed to upload picture for PlayList with Id {playList.Id} to storage."); return Result.Error($"Failed to upload picture for PlayList with Id {playList.Id} to storage.");
} }
playList.OriginalPictureKeyName = pictureName; playList.OriginalPictureName = pictureName;
logger.LogInformation("Playlist image uploaded successfully for PlayList with Id={PlayListId}.", playList.Id); logger.LogInformation("Playlist image uploaded successfully for PlayList with Id={PlayListId}.", playList.Id);
try try
@@ -30,15 +30,15 @@ namespace Musify.Application.PlayLists.Handlers
var keysToRemove = new List<string>(); var keysToRemove = new List<string>();
if (playList.SmallPictureKeyName != playListConfiguration.Routes.PresetSmallPicture) if (playList.SmallPictureName != playListConfiguration.Routes.PresetSmallPicture)
keysToRemove.Add(Path.Combine(playListConfiguration.Routes.SmallPicturesPath, keysToRemove.Add(Path.Combine(playListConfiguration.Routes.SmallPicturesPath,
playList.SmallPictureKeyName)); playList.SmallPictureName));
if (playList.MediumPictureKeyName != playListConfiguration.Routes.PresetMediumPicture) if (playList.MediumPictureName != playListConfiguration.Routes.PresetMediumPicture)
keysToRemove.Add(Path.Combine(playListConfiguration.Routes.MediumPicturesPath, keysToRemove.Add(Path.Combine(playListConfiguration.Routes.MediumPicturesPath,
playList.MediumPictureKeyName)); playList.MediumPictureName));
if (playList.LargePictureKeyName != playListConfiguration.Routes.PresetLargePicture) if (playList.LargePictureName != playListConfiguration.Routes.PresetLargePicture)
keysToRemove.Add(Path.Combine(playListConfiguration.Routes.LargePicturesPath, keysToRemove.Add(Path.Combine(playListConfiguration.Routes.LargePicturesPath,
playList.LargePictureKeyName)); playList.LargePictureName));
foreach (var key in keysToRemove) foreach (var key in keysToRemove)
{ {
@@ -48,7 +48,7 @@ namespace Musify.Application.PlayLists.Handlers
{ {
if (publishResult.IsNotFound()) if (publishResult.IsNotFound())
{ {
logger.LogWarning("File with key={KeyName} not found in storage while trying to publish remove file event for PlayList with id={PlayListId}.", key, playList.Id); logger.LogWarning("File with key={Key} not found in storage while trying to publish remove file event for PlayList with id={PlayListId}.", key, playList.Id);
continue; continue;
} }
@@ -62,19 +62,19 @@ namespace Musify.Application.PlayLists.Handlers
return Result.NoContent(); return Result.NoContent();
} }
async Task<Result> TryPublishRemoveFileEventAsync(Guid playListId, string keyName, CancellationToken cancellationToken) async Task<Result> TryPublishRemoveFileEventAsync(Guid playListId, string key, CancellationToken cancellationToken)
{ {
try try
{ {
await eventBus.PublishAsync(new RemoveFileEvent( await eventBus.PublishAsync(new RemoveFileEvent(
storageConfiguration.BucketName, storageConfiguration.BucketName,
keyName), cancellationToken); key), cancellationToken);
return Result.Success(); return Result.Success();
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Failed to publish remove file event for PlayList id={PlayListId} and key={KeyName}.", playListId, keyName); logger.LogError(exception, "Failed to publish remove file event for PlayList id={PlayListId} and key={Key}.", playListId, key);
return Result.Error($"Failed to publish remove file event for PlayList with id {playListId}."); return Result.Error($"Failed to publish remove file event for PlayList with id {playListId}.");
} }
} }
@@ -23,13 +23,13 @@ namespace Musify.Application.PlayLists.Handlers
if (playList is null) if (playList is null)
{ {
logger.LogInformation("PlayList with id {PlayListId} not found", request.PlayListId); logger.LogInformation("PlayList with id={PlayListId} not found", request.PlayListId);
return Result.NotFound(); return Result.NotFound();
} }
if (playList.UserId != request.UserId) if (playList.UserId != request.UserId)
{ {
logger.LogWarning("User with id {UserId} is not the owner of the PlayList with id {PlayListId}", request.UserId, request.PlayListId); logger.LogWarning("User with id={UserId} is not the owner of the PlayList with id={PlayListId}", request.UserId, request.PlayListId);
return Result.Unauthorized(); return Result.Unauthorized();
} }
@@ -51,20 +51,20 @@ namespace Musify.Application.PlayLists.Handlers
return Result.Success(PlayListResponse.FromEntity(playList)); return Result.Success(PlayListResponse.FromEntity(playList));
} }
if (playList.SmallPictureKeyName != playListConfiguration.Routes.PresetSmallPicture) if (playList.SmallPictureName != playListConfiguration.Routes.PresetSmallPicture)
await PublishRemoveFileEvent(Path.Combine( await PublishRemoveFileEvent(Path.Combine(
playListConfiguration.Routes.SmallPicturesPath, playListConfiguration.Routes.SmallPicturesPath,
playList.SmallPictureKeyName), playList.SmallPictureName),
cancellationToken); cancellationToken);
if (playList.MediumPictureKeyName != playListConfiguration.Routes.PresetMediumPicture) if (playList.MediumPictureName != playListConfiguration.Routes.PresetMediumPicture)
await PublishRemoveFileEvent(Path.Combine( await PublishRemoveFileEvent(Path.Combine(
playListConfiguration.Routes.MediumPicturesPath, playListConfiguration.Routes.MediumPicturesPath,
playList.MediumPictureKeyName), playList.MediumPictureName),
cancellationToken); cancellationToken);
if (playList.LargePictureKeyName != playListConfiguration.Routes.PresetLargePicture) if (playList.LargePictureName != playListConfiguration.Routes.PresetLargePicture)
await PublishRemoveFileEvent(Path.Combine( await PublishRemoveFileEvent(Path.Combine(
playListConfiguration.Routes.LargePicturesPath, playListConfiguration.Routes.LargePicturesPath,
playList.LargePictureKeyName), playList.LargePictureName),
cancellationToken); cancellationToken);
var newImageId = Guid.NewGuid(); var newImageId = Guid.NewGuid();
@@ -74,7 +74,7 @@ namespace Musify.Application.PlayLists.Handlers
var uploadResult = await UploadFile(request.NewPicture, newImageStorageKey, cancellationToken); var uploadResult = await UploadFile(request.NewPicture, newImageStorageKey, cancellationToken);
if (!uploadResult.IsSuccess) if (!uploadResult.IsSuccess)
{ {
logger.LogError("Failed to upload picture for PlayList with Id={PlayListId} to storage. Storage handler returned error: {ErrorMessage}", logger.LogError("Failed to upload picture for PlayList with Id={PlayListId} to storage. Storage handler returned error?={ErrorMessage}",
playList.Id, string.Join("; ", uploadResult.Errors)); playList.Id, string.Join("; ", uploadResult.Errors));
return Result.Error($"Failed to upload picture for PlayList with Id {playList.Id} to storage."); return Result.Error($"Failed to upload picture for PlayList with Id {playList.Id} to storage.");
} }
@@ -85,14 +85,14 @@ namespace Musify.Application.PlayLists.Handlers
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Failed to publish update picture event for PlayList with id {PlayListId}.", playList.Id); logger.LogError(exception, "Failed to publish update picture event for PlayList with id={PlayListId}.", playList.Id);
return Result.Error($"Failed to publish update picture event for PlayList with id {playList.Id}."); return Result.Error($"Failed to publish update picture event for PlayList with id {playList.Id}.");
} }
database.PlayLists.Update(playList); database.PlayLists.Update(playList);
await database.SaveChangesAsync(cancellationToken); await database.SaveChangesAsync(cancellationToken);
logger.LogInformation("Updated PlayList with id={PlayListId} and picture key {PictureKey}.", playList.Id, newImageStorageKey); logger.LogInformation("Updated PlayList with id={PlayListId} and picture key={PictureKey}.", playList.Id, newImageStorageKey);
return Result.Success(PlayListResponse.FromEntity(playList)); return Result.Success(PlayListResponse.FromEntity(playList));
} }
@@ -110,7 +110,7 @@ namespace Musify.Application.PlayLists.Handlers
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Failed to publish remove file event for key {Key}.", key); logger.LogError(exception, "Failed to publish remove file event for key={Key}.", key);
return Result.Error($"Failed to publish remove file event for key {key}."); return Result.Error($"Failed to publish remove file event for key {key}.");
} }
} }
@@ -18,9 +18,9 @@ namespace Musify.Application.PlayLists.Responses
playList.Id, playList.Id,
playList.Name, playList.Name,
playList.Description, playList.Description,
playList.SmallPictureKeyName, playList.SmallPictureName,
playList.MediumPictureKeyName, playList.MediumPictureName,
playList.LargePictureKeyName, playList.LargePictureName,
playList.CreatedDate, playList.CreatedDate,
playList.UpdatedDate); playList.UpdatedDate);
} }
@@ -21,7 +21,7 @@ namespace Musify.Application.Tracks.Handler
if (userExists is null) if (userExists is null)
{ {
logger.LogWarning("User with id {UserId} not found", request.UserId); logger.LogWarning("User with id={UserId} not found", request.UserId);
return Result.NotFound($"User with id {request.UserId} not found"); return Result.NotFound($"User with id {request.UserId} not found");
} }
@@ -31,11 +31,11 @@ namespace Musify.Application.Tracks.Handler
{ {
Title = request.Title, Title = request.Title,
NormalizedTitle = request.Title.Trim().ToUpperInvariant(), NormalizedTitle = request.Title.Trim().ToUpperInvariant(),
OriginalPictureKeyName = originalPictureFileName, OriginalPictureName = originalPictureFileName,
OriginalAudioKeyName = originalAudioFileName, OriginalAudioName = originalAudioFileName,
SmallPictureKeyName = trackConfiguration.Routes.PresetMediumPicture, SmallPictureName = trackConfiguration.Routes.PresetMediumPicture,
MediumPictureKeyName = trackConfiguration.Routes.PresetMediumPicture, MediumPictureName = trackConfiguration.Routes.PresetMediumPicture,
LargePictureKeyName = trackConfiguration.Routes.PresetLargePicture, LargePictureName = trackConfiguration.Routes.PresetLargePicture,
}; };
var originalPictureKey = Path.Combine(trackConfiguration.Routes.OriginalPicturesPath, var originalPictureKey = Path.Combine(trackConfiguration.Routes.OriginalPicturesPath,
@@ -43,7 +43,7 @@ namespace Musify.Application.Tracks.Handler
var pictureUploadResult = await UploadFile(request.Picture, originalPictureKey, cancellationToken); var pictureUploadResult = await UploadFile(request.Picture, originalPictureKey, cancellationToken);
if (!pictureUploadResult.IsSuccess) if (!pictureUploadResult.IsSuccess)
{ {
logger.LogError("Failed to upload picture for track {TrackTitle}", request.Title); logger.LogError("Failed to upload picture for track={TrackTitle}", request.Title);
return Result.Error($"Failed to upload picture for track {request.Title}"); return Result.Error($"Failed to upload picture for track {request.Title}");
} }
@@ -53,7 +53,7 @@ namespace Musify.Application.Tracks.Handler
var audioUploadResult = await UploadFile(request.Audio, audioKey, cancellationToken); var audioUploadResult = await UploadFile(request.Audio, audioKey, cancellationToken);
if (!audioUploadResult.IsSuccess) if (!audioUploadResult.IsSuccess)
{ {
logger.LogError("Failed to upload audio for track {TrackTitle}", request.Title); logger.LogError("Failed to upload audio for track={TrackTitle}", request.Title);
return Result.Error($"Failed to upload audio for track {request.Title}"); return Result.Error($"Failed to upload audio for track {request.Title}");
} }
@@ -14,8 +14,6 @@ namespace Musify.Application.Users.Handlers
{ {
public async Task<Result<UserResponse>> Handle(CreateUserCommand request, CancellationToken cancellationToken) public async Task<Result<UserResponse>> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{ {
logger.LogDebug("Handling {CommandName} with Id: {UserId}", nameof(CreateUserCommand), request.Id);
var existingUser = await database.Users.SingleOrDefaultAsync(u => u.Id == request.Id, cancellationToken); var existingUser = await database.Users.SingleOrDefaultAsync(u => u.Id == request.Id, cancellationToken);
if (existingUser is not null) if (existingUser is not null)
+5 -5
View File
@@ -22,24 +22,24 @@ namespace Musify.Domain.Entities
public required string NormalizedName { get; set; } public required string NormalizedName { get; set; }
[Required] [Required]
[MaxLength(254)] [MaxLength(256)]
public required string Description { get; set; } = "No description was provided."; public required string Description { get; set; } = "No description was provided.";
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string OriginalPictureKeyName { get; set; } public required string OriginalPictureName { get; set; }
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string SmallPictureKeyName { get; set; } public required string SmallPictureName { get; set; }
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string MediumPictureKeyName { get; set; } public required string MediumPictureName { get; set; }
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string LargePictureKeyName { get; set; } public required string LargePictureName { get; set; }
[Required] [Required]
public DateTime CreatedDate { get; set; } = DateTime.UtcNow; public DateTime CreatedDate { get; set; } = DateTime.UtcNow;
+6 -6
View File
@@ -18,26 +18,26 @@ namespace Musify.Domain.Entities
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string OriginalPictureKeyName { get; set; } public required string OriginalPictureName { get; set; }
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string SmallPictureKeyName { get; set; } public required string SmallPictureName { get; set; }
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string MediumPictureKeyName { get; set; } public required string MediumPictureName { get; set; }
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string LargePictureKeyName { get; set; } public required string LargePictureName { get; set; }
[Required] [Required]
[MaxLength(64)] [MaxLength(64)]
public required string OriginalAudioKeyName { get; set; } public required string OriginalAudioName { get; set; }
[MaxLength(64)] [MaxLength(64)]
public string AudioFolderKeyName { get; set; } = string.Empty; public string AudioFolderName { get; set; } = string.Empty;
[Required] [Required]
public DateTime CreatedDate { get; set; } = DateTime.UtcNow; public DateTime CreatedDate { get; set; } = DateTime.UtcNow;
+2 -2
View File
@@ -10,10 +10,10 @@ namespace Musify.Domain.Entities
public Guid Id { get; set; } = Guid.NewGuid(); public Guid Id { get; set; } = Guid.NewGuid();
[Required] [Required]
public required string KeyName { get; set; } public required string Bucket { get; set; }
[Required] [Required]
public required string BucketName { get; set; } public required string Key { get; set; }
[Required] [Required]
public required string ContentType { get; set; } public required string ContentType { get; set; }
+17 -17
View File
@@ -18,7 +18,7 @@ namespace Musify.Infrastructure.Audio
Directory.CreateDirectory(destinationPath); Directory.CreateDirectory(destinationPath);
logger.LogInformation( logger.LogInformation(
"Starting audio transcoding to DASH. DestinationPath: {DestinationPath}, Timeout: {Timeout}, Executable: {Executable}", "Starting audio transcoding to DASH. DestinationPath={DestinationPath}, Timeout={Timeout}, Executable={Executable}",
destinationPath, destinationPath,
audioTranscoderConfiguration.TranscodingTimeout, audioTranscoderConfiguration.TranscodingTimeout,
audioTranscoderConfiguration.Ffmpeg.ExecutableName); audioTranscoderConfiguration.Ffmpeg.ExecutableName);
@@ -33,24 +33,24 @@ namespace Musify.Infrastructure.Audio
if (executionResult.ExitCode != 0) if (executionResult.ExitCode != 0)
{ {
logger.LogError( logger.LogError(
"Audio transcoding to DASH format failed with exit code {ExitCode}. Standard Output: {StandardOutput}, Standard Error: {StandardError}", "Audio transcoding to DASH format failed with exit code={ExitCode}. Standard Output={StandardOutput}, Standard Error={StandardError}",
executionResult.ExitCode, executionResult.ExitCode,
executionResult.StandardOutput, executionResult.StandardOutput,
executionResult.StandardError); executionResult.StandardError);
return Result.Error($"Audio transcoding failed with exit code {executionResult.ExitCode}. See logs for details."); return Result.Error($"Audio transcoding failed with exit code: {executionResult.ExitCode}. See logs for details.");
} }
logger.LogInformation("Audio transcoding to DASH format completed successfully. DestinationPath: {DestinationPath}", destinationPath); logger.LogInformation("Audio transcoding to DASH format completed successfully. DestinationPath={DestinationPath}", destinationPath);
return Result.Success(); return Result.Success();
} }
catch (TimeoutException timeoutException) catch (TimeoutException timeoutException)
{ {
logger.LogError(timeoutException, "Audio transcoding timed out after {Timeout}. DestinationPath: {DestinationPath}", audioTranscoderConfiguration.TranscodingTimeout, destinationPath); logger.LogError(timeoutException, "Audio transcoding timed out after={Timeout}. DestinationPath={DestinationPath}", audioTranscoderConfiguration.TranscodingTimeout, destinationPath);
return Result.Error("Audio transcoding timed out."); return Result.Error("Audio transcoding timed out.");
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "An error occurred while transcoding audio to DASH format. DestinationPath: {DestinationPath}", destinationPath); logger.LogError(exception, "An error occurred while transcoding audio to DASH format. DestinationPath={DestinationPath}", destinationPath);
return Result.Error(exception.Message); return Result.Error(exception.Message);
} }
} }
@@ -59,13 +59,13 @@ namespace Musify.Infrastructure.Audio
{ {
if (!File.Exists(filePath)) if (!File.Exists(filePath))
{ {
logger.LogWarning("Audio validation requested for a non-existing file. FilePath: {FilePath}", filePath); logger.LogWarning("Audio validation requested for a non-existing file. FilePath={FilePath}", filePath);
return Result<bool>.Error($"Audio file not found: {filePath}"); return Result<bool>.Error($"Audio file not found: {filePath}");
} }
try try
{ {
logger.LogInformation("Starting audio file validation. FilePath: {FilePath}, Timeout: {Timeout}", filePath, audioTranscoderConfiguration.TranscodingTimeout); logger.LogInformation("Starting audio file validation. FilePath={FilePath}, Timeout={Timeout}", filePath, audioTranscoderConfiguration.TranscodingTimeout);
var executionResult = await ExecuteFfmpegAsync( var executionResult = await ExecuteFfmpegAsync(
BuildValidateAudioArguments(filePath), BuildValidateAudioArguments(filePath),
@@ -77,25 +77,25 @@ namespace Musify.Infrastructure.Audio
if (!isValid) if (!isValid)
{ {
logger.LogWarning( logger.LogWarning(
"Audio validation failed for file {FilePath}. Standard Error: {StandardError}", "Audio validation failed for file={FilePath}. Standard Error={StandardError}",
filePath, filePath,
executionResult.StandardError); executionResult.StandardError);
} }
else else
{ {
logger.LogInformation("Audio validation completed successfully. FilePath: {FilePath}", filePath); logger.LogInformation("Audio validation completed successfully. FilePath={FilePath}", filePath);
} }
return Result<bool>.Success(isValid); return Result<bool>.Success(isValid);
} }
catch (TimeoutException timeoutException) catch (TimeoutException timeoutException)
{ {
logger.LogError(timeoutException, "Audio validation timed out after {Timeout} for file {FilePath}.", audioTranscoderConfiguration.TranscodingTimeout, filePath); logger.LogError(timeoutException, "Audio validation timed out after={Timeout} for file={FilePath}.", audioTranscoderConfiguration.TranscodingTimeout, filePath);
return Result<bool>.Error("Audio validation timed out."); return Result<bool>.Error("Audio validation timed out.");
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "An error occurred while validating audio file {FilePath}.", filePath); logger.LogError(exception, "An error occurred while validating audio file={FilePath}.", filePath);
return Result<bool>.Error(exception.Message); return Result<bool>.Error(exception.Message);
} }
} }
@@ -110,7 +110,7 @@ namespace Musify.Infrastructure.Audio
using var process = BuildProcess(arguments, workingDirectory, redirectStandardInput: true); using var process = BuildProcess(arguments, workingDirectory, redirectStandardInput: true);
process.Start(); process.Start();
logger.LogDebug("[{Operation}] ffmpeg process started. ProcessId: {ProcessId}, WorkingDirectory: {WorkingDirectory}", operationName, process.Id, workingDirectory); logger.LogDebug("[{Operation}] ffmpeg process started. ProcessId={ProcessId}, WorkingDirectory={WorkingDirectory}", operationName, process.Id, workingDirectory);
if (inputStream.CanSeek) if (inputStream.CanSeek)
inputStream.Position = 0; inputStream.Position = 0;
@@ -130,7 +130,7 @@ namespace Musify.Infrastructure.Audio
using var process = BuildProcess(arguments, workingDirectory, redirectStandardInput: false); using var process = BuildProcess(arguments, workingDirectory, redirectStandardInput: false);
process.Start(); process.Start();
logger.LogDebug("[{Operation}] ffmpeg process started. ProcessId: {ProcessId}, WorkingDirectory: {WorkingDirectory}", operationName, process.Id, workingDirectory); logger.LogDebug("[{Operation}] ffmpeg process started. ProcessId={ProcessId}, WorkingDirectory={WorkingDirectory}", operationName, process.Id, workingDirectory);
return await WaitForProcessResultAsync(process, operationName, cancellationToken); return await WaitForProcessResultAsync(process, operationName, cancellationToken);
} }
@@ -169,7 +169,7 @@ namespace Musify.Infrastructure.Audio
catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
{ {
logger.LogError( logger.LogError(
"[{Operation}] ffmpeg timed out after {Timeout}. ProcessId: {ProcessId}", "[{Operation}] ffmpeg timed out after={Timeout}. ProcessId={ProcessId}",
operationName, operationName,
audioTranscoderConfiguration.TranscodingTimeout, audioTranscoderConfiguration.TranscodingTimeout,
process.Id); process.Id);
@@ -182,7 +182,7 @@ namespace Musify.Infrastructure.Audio
var standardOutput = await outputTask; var standardOutput = await outputTask;
logger.LogDebug( logger.LogDebug(
"[{Operation}] ffmpeg finished. ProcessId: {ProcessId}, ExitCode: {ExitCode}, StdOutLength: {StdOutLength}, StdErrLength: {StdErrLength}", "[{Operation}] ffmpeg finished. ProcessId={ProcessId}, ExitCode={ExitCode}, StdOutLength={StdOutLength}, StdErrLength={StdErrLength}",
operationName, operationName,
process.Id, process.Id,
process.ExitCode, process.ExitCode,
@@ -201,7 +201,7 @@ namespace Musify.Infrastructure.Audio
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Failed to kill ffmpeg process. ProcessId: {ProcessId}", process.Id); logger.LogError(exception, "Failed to kill ffmpeg process. ProcessId={ProcessId}", process.Id);
} }
} }
@@ -23,12 +23,12 @@ namespace Musify.Infrastructure.Identity
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
logger.LogError("Operation to retrieve Keycloak user with id {KeycloakId} was cancelled.", keycloakId); logger.LogError("Operation to retrieve Keycloak user with id={KeycloakId} was cancelled.", keycloakId);
return Result.Error("Operation was cancelled."); return Result.Error("Operation was cancelled.");
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogWarning(exception, "Keycloak user with id {KeycloakId} could not be retrieved.", keycloakId); logger.LogWarning(exception, "Keycloak user with id={KeycloakId} could not be retrieved.", keycloakId);
return Result.NotFound(); return Result.NotFound();
} }
return Result.Success(KeycloakUserMapper.Map(keycloakUser)); return Result.Success(KeycloakUserMapper.Map(keycloakUser));
@@ -38,7 +38,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
Directory.CreateDirectory(workingDirectory); Directory.CreateDirectory(workingDirectory);
logger.LogDebug("Generated audio workflow paths. WorkingDirectory: {WorkingDirectory}, SourceFilePath: {SourceFilePath}", logger.LogDebug("Generated audio workflow paths. WorkingDirectory={WorkingDirectory}, SourceFilePath={SourceFilePath}",
workingDirectory, workingDirectory,
sourceFilePath); sourceFilePath);
@@ -53,7 +53,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error generating audio workflow paths for key {SourceKeyName}", logger.LogError(exception, "Error generating audio workflow paths for key={SourceKey}",
executeContext.Arguments.SourceKey); executeContext.Arguments.SourceKey);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
throw; throw;
@@ -48,7 +48,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
if (!result.IsSuccess) if (!result.IsSuccess)
{ {
var errorMessage = string.Join("; ", result.Errors); var errorMessage = string.Join("; ", result.Errors);
logger.LogError("Transcoding failed for file {SourceFilePath}. Errors: {ErrorMessage}", logger.LogError("Transcoding failed for file={SourceFilePath}. Errors={ErrorMessage}",
sourceFilePath, errorMessage); sourceFilePath, errorMessage);
throw new Exception(errorMessage); throw new Exception(errorMessage);
} }
@@ -60,7 +60,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error during transcoding activity for file {SourceFilePath}", logger.LogError(exception, "Error during transcoding activity for file={SourceFilePath}",
sourceFilePath); sourceFilePath);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
throw; throw;
@@ -74,13 +74,13 @@ namespace Musify.Infrastructure.MassTransit.Activities
if (Directory.Exists(compensateContext.Log.WorkingDirectory)) if (Directory.Exists(compensateContext.Log.WorkingDirectory))
Directory.Delete(compensateContext.Log.WorkingDirectory, recursive: true); Directory.Delete(compensateContext.Log.WorkingDirectory, recursive: true);
else else
logger.LogWarning("Working directory {WorkingDirectory} does not exist during compensation", logger.LogWarning("Working directory={WorkingDirectory} does not exist during compensation",
compensateContext.Log.WorkingDirectory); compensateContext.Log.WorkingDirectory);
return Task.FromResult(compensateContext.Compensated()); return Task.FromResult(compensateContext.Compensated());
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error compensating transcoded audio directory {WorkingDirectory}", compensateContext.Log.WorkingDirectory); logger.LogError(exception, "Error compensating transcoded audio directory={WorkingDirectory}", compensateContext.Log.WorkingDirectory);
return Task.FromResult(compensateContext.Failed(exception)); return Task.FromResult(compensateContext.Failed(exception));
} }
} }
@@ -39,21 +39,21 @@ namespace Musify.Infrastructure.MassTransit.Activities.Audio
if (track is null) if (track is null)
{ {
logger.LogWarning("Track with id {TrackId} not found", logger.LogWarning("Track with id={TrackId} not found",
executeContext.Arguments.TrackId); executeContext.Arguments.TrackId);
throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found"); throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found");
} }
var log = new UpdateTrackAudioLog( var log = new UpdateTrackAudioLog(
track.Id, track.Id,
track.AudioFolderKeyName); track.AudioFolderName);
track.AudioFolderKeyName = Path.GetFileName(executeContext.Arguments.AudioFolderKey); track.AudioFolderName = Path.GetFileName(executeContext.Arguments.AudioFolderKey);
database.Tracks.Update(track); database.Tracks.Update(track);
await database.SaveChangesAsync(executeContext.CancellationToken); await database.SaveChangesAsync(executeContext.CancellationToken);
logger.LogInformation("Updated Track {TrackId} audio", logger.LogInformation("Updated Track={TrackId} audio",
executeContext.Arguments.TrackId); executeContext.Arguments.TrackId);
await processTrackingStore.CompleteStepAsync(processId, stepId, executeContext.CancellationToken); await processTrackingStore.CompleteStepAsync(processId, stepId, executeContext.CancellationToken);
@@ -61,7 +61,7 @@ namespace Musify.Infrastructure.MassTransit.Activities.Audio
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error updating Track {TrackId} audio", logger.LogError(exception, "Error updating Track={TrackId} audio",
executeContext.Arguments.TrackId); executeContext.Arguments.TrackId);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
throw; throw;
@@ -81,7 +81,7 @@ namespace Musify.Infrastructure.MassTransit.Activities.Audio
return compensateContext.Compensated(); return compensateContext.Compensated();
} }
track.AudioFolderKeyName = compensateContext.Log.PreviousFolderAudioKey; track.AudioFolderName = compensateContext.Log.PreviousFolderAudioKey;
database.Tracks.Update(track); database.Tracks.Update(track);
await database.SaveChangesAsync(compensateContext.CancellationToken); await database.SaveChangesAsync(compensateContext.CancellationToken);
@@ -90,7 +90,7 @@ namespace Musify.Infrastructure.MassTransit.Activities.Audio
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error compensating Track {TrackId} audio", compensateContext.Log.TrackId); logger.LogError(exception, "Error compensating Track={TrackId} audio", compensateContext.Log.TrackId);
return compensateContext.Failed(exception); return compensateContext.Failed(exception);
} }
} }
@@ -44,7 +44,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
if (!getFile.IsSuccess) if (!getFile.IsSuccess)
{ {
var errorMessage = string.Join("; ", getFile.Errors); var errorMessage = string.Join("; ", getFile.Errors);
logger.LogWarning("Failed to download file from bucket. Bucket: {BucketName}, Key: {KeyName}, Errors: {Errors}", logger.LogWarning("Failed to download file from bucket. Bucket={Bucket}, Key={Key}, Errors={Errors}",
executeContext.Arguments.Bucket, executeContext.Arguments.Bucket,
executeContext.Arguments.Key, executeContext.Arguments.Key,
errorMessage); errorMessage);
@@ -85,7 +85,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error compensating downloaded file {DestinationFilePath}", compensateContext.Log.DestinationFilePath); logger.LogError(exception, "Error compensating downloaded file={DestinationFilePath}", compensateContext.Log.DestinationFilePath);
return Task.FromResult(compensateContext.Failed(exception)); return Task.FromResult(compensateContext.Failed(exception));
} }
} }
@@ -40,7 +40,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
if (!removeFile.IsSuccess) if (!removeFile.IsSuccess)
{ {
var errorMessage = string.Join("; ", removeFile.Errors); var errorMessage = string.Join("; ", removeFile.Errors);
logger.LogWarning("Failed to remove file {KeyName} from bucket {BucketName}. Errors: {Errors}", logger.LogWarning("Failed to remove file={Key} from bucket={Bucket}. Errors={Errors}",
executeContext.Arguments.Key, executeContext.Arguments.Key,
executeContext.Arguments.Bucket, executeContext.Arguments.Bucket,
errorMessage); errorMessage);
@@ -51,7 +51,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error removing file {KeyName} from bucket {BucketName}", logger.LogError(exception, "Error removing file={Key} from bucket={Bucket}",
executeContext.Arguments.Key, executeContext.Arguments.Key,
executeContext.Arguments.Bucket); executeContext.Arguments.Bucket);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
@@ -51,7 +51,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
if (!transferFilesResult.IsSuccess) if (!transferFilesResult.IsSuccess)
{ {
var errorMessage = string.Join("; ", transferFilesResult.Errors); var errorMessage = string.Join("; ", transferFilesResult.Errors);
logger.LogWarning("Failed to transfer files from {FolderPath} to bucket {DestinationBucketName}, key {DestinationKeyName}. Errors: {Errors}", logger.LogWarning("Failed to transfer files from={FolderPath} to bucket={DestinationBucket}, key={DestinationKey}. Errors={Errors}",
folderPath, folderPath,
executeContext.Arguments.DestinationBucket, executeContext.Arguments.DestinationBucket,
destinationKey, destinationKey,
@@ -64,7 +64,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error transferring files from {FolderPath} to bucket {DestinationBucketName}", logger.LogError(exception, "Error transferring files from={FolderPath} to bucket={DestinationBucket}",
folderPath, folderPath,
executeContext.Arguments.DestinationBucket); executeContext.Arguments.DestinationBucket);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
@@ -88,7 +88,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error compensating transferred files to bucket {DestinationBucketName}", compensateContext.Log.DestinationBucket); logger.LogError(exception, "Error compensating transferred files to bucket={DestinationBucket}", compensateContext.Log.DestinationBucket);
return compensateContext.Failed(exception); return compensateContext.Failed(exception);
} }
} }
@@ -46,7 +46,7 @@ namespace Musify.Infrastructure.MassTransit.Activities.Files
if (!uploadResult.IsSuccess) if (!uploadResult.IsSuccess)
{ {
var errors = string.Join("; ", uploadResult.Errors); var errors = string.Join("; ", uploadResult.Errors);
logger.LogWarning("Failed to upload file to bucket. Bucket: {BucketName}, Key: {KeyName}, Errors: {Errors}", logger.LogWarning("Failed to upload file to bucket. Bucket={Bucket}, Key={Key}, Errors={Errors}",
executeContext.Arguments.DestinationBucket, executeContext.Arguments.DestinationBucket,
executeContext.Arguments.DestinationRoute, executeContext.Arguments.DestinationRoute,
errors); errors);
@@ -60,7 +60,7 @@ namespace Musify.Infrastructure.MassTransit.Activities.Files
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "An error occurred while uploading file to bucket for process {ProcessId} at step {StepId}", processId, stepId); logger.LogError(exception, "An error occurred while uploading file to bucket for process={ProcessId} at step={StepId}", processId, stepId);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
throw; throw;
} }
@@ -78,16 +78,15 @@ namespace Musify.Infrastructure.MassTransit.Activities.Files
if (!uploadResult.IsSuccess) if (!uploadResult.IsSuccess)
{ {
var errors = string.Join("; ", uploadResult.Errors); var errors = string.Join("; ", uploadResult.Errors);
var errorMessage = $"Failed to remove file from bucket during compensation. Bucket: {compensateContext.Log.DestinationBucket}, Key: {compensateContext.Log.DestinationKey}, Errors: {errors}"; logger.LogError($"Failed to remove file from bucket during compensation. Bucket={compensateContext.Log.DestinationBucket}, Key={compensateContext.Log.DestinationKey}, Errors={errors}");
logger.LogError(errorMessage); return compensateContext.Failed(new Exception($"Failed to remove file from bucket during compensation. Bucket: {compensateContext.Log.DestinationBucket}, Key: {compensateContext.Log.DestinationKey}, Errors: {errors}"));
return compensateContext.Failed(new Exception(errorMessage));
} }
return compensateContext.Compensated(); return compensateContext.Compensated();
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "An error occurred while compensating upload file to bucket activity for bucket {BucketName} and key {KeyName}", logger.LogError(exception, "An error occurred while compensating upload file to bucket activity for bucket={Bucket} and key={Key}",
compensateContext.Log.DestinationBucket, compensateContext.Log.DestinationBucket,
compensateContext.Log.DestinationKey); compensateContext.Log.DestinationKey);
return compensateContext.Failed(exception); return compensateContext.Failed(exception);
@@ -47,7 +47,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
Directory.CreateDirectory(workingDirectory); Directory.CreateDirectory(workingDirectory);
logger.LogDebug("Generated picture workflow paths. WorkingDirectory: {WorkingDirectory}, SourceFilePath: {SourceFilePath}", logger.LogDebug("Generated picture workflow paths. WorkingDirectory={WorkingDirectory}, SourceFilePath={SourceFilePath}",
workingDirectory, workingDirectory,
sourceFilePath); sourceFilePath);
@@ -64,7 +64,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error generating picture workflow paths for key {SourceKeyName}", logger.LogError(exception, "Error generating picture workflow paths for key={SourceKey}",
executeContext.Arguments.SourceKey); executeContext.Arguments.SourceKey);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
throw; throw;
@@ -41,7 +41,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
{ {
if (!File.Exists(sourceFilePath)) if (!File.Exists(sourceFilePath))
{ {
logger.LogWarning("Source file not found at {SourceFilePath}", sourceFilePath); logger.LogWarning("Source file not found at={SourceFilePath}", sourceFilePath);
throw new FileNotFoundException($"Source file not found: {sourceFilePath}"); throw new FileNotFoundException($"Source file not found: {sourceFilePath}");
} }
@@ -56,7 +56,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
if (!resizedPicture.IsSuccess) if (!resizedPicture.IsSuccess)
{ {
var errorMessage = string.Join("; ", resizedPicture.Errors); var errorMessage = string.Join("; ", resizedPicture.Errors);
logger.LogError("Failed to resize picture {SourceFilePath} to {Width}x{Height}. Errors: {Errors}", logger.LogError("Failed to resize picture={SourceFilePath} to={Width}x{Height}. Errors={Errors}",
sourceFilePath, sourceFilePath,
executeContext.Arguments.Width, executeContext.Arguments.Width,
executeContext.Arguments.Height, executeContext.Arguments.Height,
@@ -71,18 +71,16 @@ namespace Musify.Infrastructure.MassTransit.Activities
await using var destinationStream = File.Create(destinationFilePath); await using var destinationStream = File.Create(destinationFilePath);
await resizedPicture.Value.CopyToAsync(destinationStream, executeContext.CancellationToken); await resizedPicture.Value.CopyToAsync(destinationStream, executeContext.CancellationToken);
logger.LogDebug("Picture resized from {SourceFilePath} to {DestinationFilePath} ({Width}x{Height})", logger.LogDebug("Picture resized from={SourceFilePath} to={DestinationFilePath}",
sourceFilePath, sourceFilePath,
destinationFilePath, destinationFilePath);
executeContext.Arguments.Width,
executeContext.Arguments.Height);
await processTrackingStore.CompleteStepAsync(processId, stepId, executeContext.CancellationToken); await processTrackingStore.CompleteStepAsync(processId, stepId, executeContext.CancellationToken);
return executeContext.Completed(new ResizePictureLog(destinationFilePath)); return executeContext.Completed(new ResizePictureLog(destinationFilePath));
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error resizing picture {SourceFilePath}", sourceFilePath); logger.LogError(exception, "Error resizing picture={SourceFilePath}", sourceFilePath);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
throw; throw;
} }
@@ -97,7 +95,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error compensating resized file {DestinationFilePath}", compensateContext.Log.DestinationFilePath); logger.LogError(exception, "Error compensating resized file={DestinationFilePath}", compensateContext.Log.DestinationFilePath);
return Task.FromResult(compensateContext.Failed(exception)); return Task.FromResult(compensateContext.Failed(exception));
} }
} }
@@ -46,27 +46,27 @@ namespace Musify.Infrastructure.MassTransit.Activities
if (playList is null) if (playList is null)
{ {
logger.LogWarning("PlayList with id {PlayListId} not found", logger.LogWarning("PlayList with id={PlayListId} not found",
executeContext.Arguments.PlayListId); executeContext.Arguments.PlayListId);
throw new InvalidOperationException($"PlayList with id {executeContext.Arguments.PlayListId} not found"); throw new InvalidOperationException($"PlayList with id {executeContext.Arguments.PlayListId} not found");
} }
var log = new UpdatePlayListPictureLog( var log = new UpdatePlayListPictureLog(
playList.Id, playList.Id,
playList.OriginalPictureKeyName, playList.OriginalPictureName,
playList.SmallPictureKeyName, playList.SmallPictureName,
playList.MediumPictureKeyName, playList.MediumPictureName,
playList.LargePictureKeyName); playList.LargePictureName);
playList.OriginalPictureKeyName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey); playList.OriginalPictureName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey);
playList.SmallPictureKeyName = Path.GetFileName(smallResizedVariable); playList.SmallPictureName = Path.GetFileName(smallResizedVariable);
playList.MediumPictureKeyName = Path.GetFileName(mediumResizedVariable); playList.MediumPictureName = Path.GetFileName(mediumResizedVariable);
playList.LargePictureKeyName = Path.GetFileName(largeResizedVariable); playList.LargePictureName = Path.GetFileName(largeResizedVariable);
database.PlayLists.Update(playList); database.PlayLists.Update(playList);
await database.SaveChangesAsync(executeContext.CancellationToken); await database.SaveChangesAsync(executeContext.CancellationToken);
logger.LogInformation("Updated PlayList {PlayListId} pictures", logger.LogInformation("Updated PlayList={PlayListId} pictures",
executeContext.Arguments.PlayListId); executeContext.Arguments.PlayListId);
await processTrackingStore.CompleteStepAsync(processId, stepId, executeContext.CancellationToken); await processTrackingStore.CompleteStepAsync(processId, stepId, executeContext.CancellationToken);
@@ -74,7 +74,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error updating PlayList {PlayListId} pictures", logger.LogError(exception, "Error updating PlayList={PlayListId} pictures",
executeContext.Arguments.PlayListId); executeContext.Arguments.PlayListId);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
throw; throw;
@@ -94,10 +94,10 @@ namespace Musify.Infrastructure.MassTransit.Activities
return compensateContext.Compensated(); return compensateContext.Compensated();
} }
playList.OriginalPictureKeyName = compensateContext.Log.PreviousOriginalPictureKey; playList.OriginalPictureName = compensateContext.Log.PreviousOriginalPictureKey;
playList.SmallPictureKeyName = compensateContext.Log.PreviousSmallPictureKey; playList.SmallPictureName = compensateContext.Log.PreviousSmallPictureKey;
playList.MediumPictureKeyName = compensateContext.Log.PreviousMediumPictureKey; playList.MediumPictureName = compensateContext.Log.PreviousMediumPictureKey;
playList.LargePictureKeyName = compensateContext.Log.PreviousLargePictureKey; playList.LargePictureName = compensateContext.Log.PreviousLargePictureKey;
database.PlayLists.Update(playList); database.PlayLists.Update(playList);
await database.SaveChangesAsync(compensateContext.CancellationToken); await database.SaveChangesAsync(compensateContext.CancellationToken);
@@ -106,7 +106,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error compensating PlayList {PlayListId} pictures", compensateContext.Log.PlayListId); logger.LogError(exception, "Error compensating PlayList={PlayListId} pictures", compensateContext.Log.PlayListId);
return compensateContext.Failed(exception); return compensateContext.Failed(exception);
} }
} }
@@ -46,27 +46,27 @@ namespace Musify.Infrastructure.MassTransit.Activities
if (track is null) if (track is null)
{ {
logger.LogWarning("Track with id {TrackId} not found", logger.LogWarning("Track with id={TrackId} not found",
executeContext.Arguments.TrackId); executeContext.Arguments.TrackId);
throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found"); throw new InvalidOperationException($"Track with id {executeContext.Arguments.TrackId} not found");
} }
var log = new UpdateTrackPictureLog( var log = new UpdateTrackPictureLog(
track.Id, track.Id,
track.OriginalPictureKeyName, track.OriginalPictureName,
track.SmallPictureKeyName, track.SmallPictureName,
track.MediumPictureKeyName, track.MediumPictureName,
track.LargePictureKeyName); track.LargePictureName);
track.OriginalPictureKeyName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey); track.OriginalPictureName = Path.GetFileName(executeContext.Arguments.OriginalPictureKey);
track.SmallPictureKeyName = Path.GetFileName(smallResizedVariable); track.SmallPictureName = Path.GetFileName(smallResizedVariable);
track.MediumPictureKeyName = Path.GetFileName(mediumResizedVariable); track.MediumPictureName = Path.GetFileName(mediumResizedVariable);
track.LargePictureKeyName = Path.GetFileName(largeResizedVariable); track.LargePictureName = Path.GetFileName(largeResizedVariable);
database.Tracks.Update(track); database.Tracks.Update(track);
await database.SaveChangesAsync(executeContext.CancellationToken); await database.SaveChangesAsync(executeContext.CancellationToken);
logger.LogInformation("Updated Track {TrackId} pictures", logger.LogInformation("Updated Track={TrackId} pictures",
executeContext.Arguments.TrackId); executeContext.Arguments.TrackId);
await processTrackingStore.CompleteStepAsync(processId, stepId, executeContext.CancellationToken); await processTrackingStore.CompleteStepAsync(processId, stepId, executeContext.CancellationToken);
@@ -74,7 +74,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error updating Track {TrackId} pictures", logger.LogError(exception, "Error updating Track={TrackId} pictures",
executeContext.Arguments.TrackId); executeContext.Arguments.TrackId);
await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken); await processTrackingStore.FailStepAsync(processId, stepId, exception.Message, executeContext.CancellationToken);
throw; throw;
@@ -94,10 +94,10 @@ namespace Musify.Infrastructure.MassTransit.Activities
return compensateContext.Compensated(); return compensateContext.Compensated();
} }
track.OriginalPictureKeyName = compensateContext.Log.PreviousOriginalPictureKey; track.OriginalPictureName = compensateContext.Log.PreviousOriginalPictureKey;
track.SmallPictureKeyName = compensateContext.Log.PreviousSmallPictureKey; track.SmallPictureName = compensateContext.Log.PreviousSmallPictureKey;
track.MediumPictureKeyName = compensateContext.Log.PreviousMediumPictureKey; track.MediumPictureName = compensateContext.Log.PreviousMediumPictureKey;
track.LargePictureKeyName = compensateContext.Log.PreviousLargePictureKey; track.LargePictureName = compensateContext.Log.PreviousLargePictureKey;
database.Tracks.Update(track); database.Tracks.Update(track);
await database.SaveChangesAsync(compensateContext.CancellationToken); await database.SaveChangesAsync(compensateContext.CancellationToken);
@@ -106,7 +106,7 @@ namespace Musify.Infrastructure.MassTransit.Activities
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Error compensating Track {TrackId} pictures", compensateContext.Log.TrackId); logger.LogError(exception, "Error compensating Track={TrackId} pictures", compensateContext.Log.TrackId);
return compensateContext.Failed(exception); return compensateContext.Failed(exception);
} }
} }
@@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Musify.Infrastructure.Persistence.Migrations namespace Musify.Infrastructure.Persistence.Migrations
{ {
[DbContext(typeof(Database))] [DbContext(typeof(Database))]
[Migration("20260325003221_FirstMigration")] [Migration("20260328141805_FirstMigration")]
partial class FirstMigration partial class FirstMigration
{ {
/// <inheritdoc /> /// <inheritdoc />
@@ -36,15 +36,15 @@ namespace Musify.Infrastructure.Persistence.Migrations
b.Property<string>("Description") b.Property<string>("Description")
.IsRequired() .IsRequired()
.HasMaxLength(254) .HasMaxLength(256)
.HasColumnType("character varying(254)"); .HasColumnType("character varying(256)");
b.Property<string>("LargePictureKeyName") b.Property<string>("LargePictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("MediumPictureKeyName") b.Property<string>("MediumPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -59,12 +59,12 @@ namespace Musify.Infrastructure.Persistence.Migrations
.HasMaxLength(50) .HasMaxLength(50)
.HasColumnType("character varying(50)"); .HasColumnType("character varying(50)");
b.Property<string>("OriginalPictureKeyName") b.Property<string>("OriginalPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("SmallPictureKeyName") b.Property<string>("SmallPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -195,7 +195,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<string>("AudioFolderKeyName") b.Property<string>("AudioFolderName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -203,12 +203,12 @@ namespace Musify.Infrastructure.Persistence.Migrations
b.Property<DateTime>("CreatedDate") b.Property<DateTime>("CreatedDate")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("LargePictureKeyName") b.Property<string>("LargePictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("MediumPictureKeyName") b.Property<string>("MediumPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -218,17 +218,17 @@ namespace Musify.Infrastructure.Persistence.Migrations
.HasMaxLength(50) .HasMaxLength(50)
.HasColumnType("character varying(50)"); .HasColumnType("character varying(50)");
b.Property<string>("OriginalAudioKeyName") b.Property<string>("OriginalAudioName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("OriginalPictureKeyName") b.Property<string>("OriginalPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("SmallPictureKeyName") b.Property<string>("SmallPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -252,7 +252,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<string>("BucketName") b.Property<string>("Bucket")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
@@ -263,7 +263,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
b.Property<DateTime>("CreatedTime") b.Property<DateTime>("CreatedTime")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("KeyName") b.Property<string>("Key")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
@@ -37,12 +37,12 @@ namespace Musify.Infrastructure.Persistence.Migrations
Id = table.Column<Guid>(type: "uuid", nullable: false), Id = table.Column<Guid>(type: "uuid", nullable: false),
Title = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false), Title = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
NormalizedTitle = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false), NormalizedTitle = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
OriginalPictureKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), OriginalPictureName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
SmallPictureKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), SmallPictureName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
MediumPictureKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), MediumPictureName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
LargePictureKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), LargePictureName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
OriginalAudioKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), OriginalAudioName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
AudioFolderKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), AudioFolderName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
CreatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), CreatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false) UpdatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
}, },
@@ -56,8 +56,8 @@ namespace Musify.Infrastructure.Persistence.Migrations
columns: table => new columns: table => new
{ {
Id = table.Column<Guid>(type: "uuid", nullable: false), Id = table.Column<Guid>(type: "uuid", nullable: false),
KeyName = table.Column<string>(type: "text", nullable: false), Bucket = table.Column<string>(type: "text", nullable: false),
BucketName = table.Column<string>(type: "text", nullable: false), Key = table.Column<string>(type: "text", nullable: false),
ContentType = table.Column<string>(type: "text", nullable: false), ContentType = table.Column<string>(type: "text", nullable: false),
CreatedTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), CreatedTime = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
State = table.Column<int>(type: "integer", nullable: false) State = table.Column<int>(type: "integer", nullable: false)
@@ -113,11 +113,11 @@ namespace Musify.Infrastructure.Persistence.Migrations
UserId = table.Column<Guid>(type: "uuid", nullable: false), UserId = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false), Name = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
NormalizedName = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false), NormalizedName = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
Description = table.Column<string>(type: "character varying(254)", maxLength: 254, nullable: false), Description = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false),
OriginalPictureKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), OriginalPictureName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
SmallPictureKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), SmallPictureName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
MediumPictureKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), MediumPictureName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
LargePictureKeyName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false), LargePictureName = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
CreatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false), CreatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
UpdatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false) UpdatedDate = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
}, },
@@ -33,15 +33,15 @@ namespace Musify.Infrastructure.Persistence.Migrations
b.Property<string>("Description") b.Property<string>("Description")
.IsRequired() .IsRequired()
.HasMaxLength(254) .HasMaxLength(256)
.HasColumnType("character varying(254)"); .HasColumnType("character varying(256)");
b.Property<string>("LargePictureKeyName") b.Property<string>("LargePictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("MediumPictureKeyName") b.Property<string>("MediumPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -56,12 +56,12 @@ namespace Musify.Infrastructure.Persistence.Migrations
.HasMaxLength(50) .HasMaxLength(50)
.HasColumnType("character varying(50)"); .HasColumnType("character varying(50)");
b.Property<string>("OriginalPictureKeyName") b.Property<string>("OriginalPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("SmallPictureKeyName") b.Property<string>("SmallPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -192,7 +192,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<string>("AudioFolderKeyName") b.Property<string>("AudioFolderName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -200,12 +200,12 @@ namespace Musify.Infrastructure.Persistence.Migrations
b.Property<DateTime>("CreatedDate") b.Property<DateTime>("CreatedDate")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("LargePictureKeyName") b.Property<string>("LargePictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("MediumPictureKeyName") b.Property<string>("MediumPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -215,17 +215,17 @@ namespace Musify.Infrastructure.Persistence.Migrations
.HasMaxLength(50) .HasMaxLength(50)
.HasColumnType("character varying(50)"); .HasColumnType("character varying(50)");
b.Property<string>("OriginalAudioKeyName") b.Property<string>("OriginalAudioName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("OriginalPictureKeyName") b.Property<string>("OriginalPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
b.Property<string>("SmallPictureKeyName") b.Property<string>("SmallPictureName")
.IsRequired() .IsRequired()
.HasMaxLength(64) .HasMaxLength(64)
.HasColumnType("character varying(64)"); .HasColumnType("character varying(64)");
@@ -249,7 +249,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<string>("BucketName") b.Property<string>("Bucket")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
@@ -260,7 +260,7 @@ namespace Musify.Infrastructure.Persistence.Migrations
b.Property<DateTime>("CreatedTime") b.Property<DateTime>("CreatedTime")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("KeyName") b.Property<string>("Key")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
+3 -3
View File
@@ -13,7 +13,7 @@ namespace Musify.Infrastructure.Pictures
{ {
try try
{ {
logger.LogDebug("Resizing picture to {Width}x{Height}", width, height); logger.LogDebug("Resizing picture to={Width}x{Height}", width, height);
if (pictureStream.CanSeek && pictureStream.Position > 0) if (pictureStream.CanSeek && pictureStream.Position > 0)
pictureStream.Position = 0; pictureStream.Position = 0;
@@ -31,12 +31,12 @@ namespace Musify.Infrastructure.Pictures
memoryStream.Position = 0; memoryStream.Position = 0;
logger.LogDebug("Picture resized successfully. OutputLength: {Length}", memoryStream.Length); logger.LogDebug("Picture resized successfully. OutputLength={Length}", memoryStream.Length);
return Result<Stream>.Success(memoryStream); return Result<Stream>.Success(memoryStream);
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "An error occurred while resizing the picture to {Width}x{Height}.", width, height); logger.LogError(exception, "An error occurred while resizing the picture to={Width}x{Height}.", width, height);
return Result.Error("An error occurred while resizing the picture."); return Result.Error("An error occurred while resizing the picture.");
} }
} }
+48 -48
View File
@@ -13,61 +13,61 @@ namespace Musify.Infrastructure.Storage
public class StorageHandler(IDatabase database, IAmazonS3 amazonS3, InfrastructureStorageConfiguration storageClientConfiguration, ILogger<StorageHandler> logger) public class StorageHandler(IDatabase database, IAmazonS3 amazonS3, InfrastructureStorageConfiguration storageClientConfiguration, ILogger<StorageHandler> logger)
: IStorageHandler : IStorageHandler
{ {
public async Task<Result<Stream>> GetFileAsync(string bucketName, string keyName, CancellationToken cancellationToken) public async Task<Result<Stream>> GetFileAsync(string bucket, string key, CancellationToken cancellationToken)
{ {
var request = new GetObjectRequest var request = new GetObjectRequest
{ {
BucketName = bucketName, BucketName = bucket,
Key = keyName, Key = key,
}; };
logger.LogDebug("Getting file from S3. Bucket: {BucketName}, Key: {KeyName}", bucketName, keyName); logger.LogDebug("Getting file from S3. Bucket={Bucket}, Key={Key}", bucket, key);
try try
{ {
var response = await amazonS3.GetObjectAsync(request, cancellationToken); var response = await amazonS3.GetObjectAsync(request, cancellationToken);
logger.LogDebug("Successfully got file from S3 with bucket name {BucketName} and key name {KeyName}", bucketName, keyName); logger.LogDebug("Successfully got file from S3 with bucket={Bucket} and key={Key}", bucket, key);
return Result.Success(response.ResponseStream); return Result.Success(response.ResponseStream);
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogWarning(exception, "Failed to get file from S3. Bucket: {BucketName}, Key: {KeyName}", bucketName, keyName); logger.LogWarning(exception, "Failed to get file from S3. Bucket={Bucket}, Key={Key}", bucket, key);
return Result.NotFound($"File not found in S3 with bucket name {bucketName} and key name {keyName}"); return Result.NotFound($"File not found in S3 with bucket: {bucket} and key: {key}");
} }
} }
public async Task<string> GetUrlAsync(string bucketName, string keyName, TimeSpan expirationTime, CancellationToken cancellationToken) public async Task<string> GetUrlAsync(string bucket, string key, TimeSpan expirationTime, CancellationToken cancellationToken)
{ {
var request = new GetPreSignedUrlRequest var request = new GetPreSignedUrlRequest
{ {
BucketName = bucketName, BucketName = bucket,
Key = keyName, Key = key,
Expires = DateTime.UtcNow + expirationTime, Expires = DateTime.UtcNow + expirationTime,
Protocol = storageClientConfiguration.UseHttp ? Protocol.HTTP : Protocol.HTTPS Protocol = storageClientConfiguration.UseHttp ? Protocol.HTTP : Protocol.HTTPS
}; };
logger.LogDebug("Getting pre-signed URL from S3. Bucket: {BucketName}, Key: {KeyName}, Expires: {Expires}", bucketName, keyName, request.Expires); logger.LogDebug("Getting pre-signed URL from S3. Bucket={BucketName}, Key={Key}, Expires={Expires}", bucket, key, request.Expires);
var url = await amazonS3.GetPreSignedURLAsync(request); var url = await amazonS3.GetPreSignedURLAsync(request);
return url; return url;
} }
public async Task<Result> RemoveFileAsync(string bucketName, string keyName, CancellationToken cancellationToken) public async Task<Result> RemoveFileAsync(string bucket, string key, CancellationToken cancellationToken)
{ {
var request = new DeleteObjectRequest var request = new DeleteObjectRequest
{ {
BucketName = bucketName, BucketName = bucket,
Key = keyName, Key = key,
}; };
logger.LogDebug("Removing file from S3. Bucket: {BucketName}, Key: {KeyName}", bucketName, keyName); logger.LogDebug("Removing file from S3. Bucket={Bucket}, Key={Key}", bucket, key);
var response = await amazonS3.DeleteObjectAsync(request, cancellationToken); var response = await amazonS3.DeleteObjectAsync(request, cancellationToken);
return Result.NoContent(); return Result.NoContent();
} }
public async Task<Result> TransferFilesAsync(string sourceDirectory, string bucketName, string route, CancellationToken cancellationToken) public async Task<Result> TransferFilesAsync(string sourceDirectory, string bucket, string route, CancellationToken cancellationToken)
{ {
var trasnsferUtility = new TransferUtility(amazonS3); var trasnsferUtility = new TransferUtility(amazonS3);
@@ -81,67 +81,67 @@ namespace Musify.Infrastructure.Storage
string fileName = Path.GetFileName(file); string fileName = Path.GetFileName(file);
string filePath = Path.Combine(sourceDirectory, file); string filePath = Path.Combine(sourceDirectory, file);
var keyName = Path.Combine(route, fileName); var key = Path.Combine(route, fileName);
var upload = new Upload var upload = new Upload
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
BucketName = bucketName, Bucket = bucket,
KeyName = keyName, Key = key,
ContentType = "Application/Octet-Stream" ContentType = MimeUtility.GetMimeMapping(filePath)
}; };
await database.Uploads.AddAsync(upload, cancellationToken); await database.Uploads.AddAsync(upload, cancellationToken);
try try
{ {
await trasnsferUtility.UploadAsync(filePath, bucketName, keyName, cancellationToken); await trasnsferUtility.UploadAsync(filePath, bucket, key, cancellationToken);
upload.State = UploadState.Successful; upload.State = UploadState.Successful;
successCount++; successCount++;
logger.LogDebug("Transferred file to S3. Bucket: {BucketName}, KeyName: {KeyName}", bucketName, keyName); logger.LogDebug("Transferred file to S3. Bucket={Bucket}, Key={Key}", bucket, key);
} }
catch (Exception exception) catch (Exception exception)
{ {
failedCount++; failedCount++;
upload.State = UploadState.Failed; upload.State = UploadState.Failed;
logger.LogError(exception, "Failed to transfer file to S3. Bucket: {BucketName}, keyName: {keyName}", bucketName, keyName); logger.LogError(exception, "Failed to transfer file to S3. Bucket={Bucket}, key={key}", bucket, key);
} }
} }
await database.SaveChangesAsync(cancellationToken); await database.SaveChangesAsync(cancellationToken);
logger.LogInformation("TransferFiles completed. Bucket: {BucketName}, Route: {Route}, Success: {SuccessCount}, Failed: {FailedCount}", bucketName, route, successCount, failedCount); logger.LogInformation("TransferFiles completed. Bucket={Bucket}, Route={Route}, Success={SuccessCount}, Failed={FailedCount}", bucket, route, successCount, failedCount);
return Result.Success(); return Result.Success();
} }
public async Task<Result<string>> UploadFileAsync(string filePath, string bucketName, string keyName, CancellationToken cancellationToken) public async Task<Result<string>> UploadFileAsync(string filePath, string bucket, string key, CancellationToken cancellationToken)
{ {
try try
{ {
using var fileStream = File.OpenRead(filePath); using var fileStream = File.OpenRead(filePath);
var contentType = MimeUtility.GetMimeMapping(filePath); var contentType = MimeUtility.GetMimeMapping(filePath);
return await UploadFileAsync(fileStream, contentType, bucketName, keyName, cancellationToken); return await UploadFileAsync(fileStream, contentType, bucket, key, cancellationToken);
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Failed to upload file to S3 with bucket name {BucketName} and key name {KeyName}", bucketName, keyName); logger.LogError(exception, "Failed to upload file to S3 with bucket={Bucket} and key={Key}", bucket, key);
return Result.Error($"Failed to upload file to S3 with bucket name {bucketName} and key name {keyName}"); return Result.Error($"Failed to upload file to S3 with bucket: {bucket} and key: {key}");
} }
} }
public async Task<Result<string>> UploadFileAsync(Stream sourceStream, string contentType, string bucketName, string keyName, CancellationToken cancellationToken) public async Task<Result<string>> UploadFileAsync(Stream sourceStream, string contentType, string bucket, string key, CancellationToken cancellationToken)
{ {
var request = new PutObjectRequest var request = new PutObjectRequest
{ {
BucketName = bucketName, BucketName = bucket,
ContentType = contentType, ContentType = contentType,
InputStream = sourceStream, InputStream = sourceStream,
Key = keyName Key = key
}; };
var upload = new Upload var upload = new Upload
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
BucketName = bucketName, Bucket = bucket,
KeyName = keyName, Key = key,
ContentType = contentType ContentType = contentType
}; };
await database.Uploads.AddAsync(upload, cancellationToken); await database.Uploads.AddAsync(upload, cancellationToken);
@@ -149,45 +149,45 @@ namespace Musify.Infrastructure.Storage
try try
{ {
var response = await amazonS3.PutObjectAsync(request, cancellationToken); var response = await amazonS3.PutObjectAsync(request, cancellationToken);
logger.LogDebug("Uploaded file to S3. Bucket: {BucketName}, Key: {KeyName}", bucketName, keyName); logger.LogDebug("Uploaded file to S3. Bucket?={Bucket}, Key={Key}", bucket, key);
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Failed to upload file to S3 with bucket name {BucketName} and key name {KeyName}", bucketName, keyName); logger.LogError(exception, "Failed to upload file to S3 with bucket={Bucket} and key={Key}", bucket, key);
upload.State = UploadState.Failed; upload.State = UploadState.Failed;
return Result.Error($"Failed to upload file to S3 with bucket name {bucketName} and key name {keyName}"); return Result.Error($"Failed to upload file to S3 with bucket: {bucket} and key: {key}");
} }
upload.State = UploadState.Successful; upload.State = UploadState.Successful;
await database.SaveChangesAsync(cancellationToken); await database.SaveChangesAsync(cancellationToken);
logger.LogDebug("Saved upload record to database. Bucket: {BucketName}, Key: {KeyName}", bucketName, keyName); logger.LogDebug("Saved upload record to database. Bucket={Bucket}, Key={Key}", bucket, key);
return Result.Success(keyName); return Result.Success(key);
} }
public async Task<Result> CopyFileAsync(string sourceBucketName, string sourceKeyName, string destinationBucketName, string destinationKeyName, public async Task<Result> CopyFileAsync(string sourceBucket, string sourceKey, string destinationBucket, string destinationKey,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var request = new CopyObjectRequest var request = new CopyObjectRequest
{ {
SourceBucket = sourceBucketName, SourceBucket = sourceBucket,
SourceKey = sourceKeyName, SourceKey = sourceKey,
DestinationBucket = destinationBucketName, DestinationBucket = destinationBucket,
DestinationKey = destinationKeyName DestinationKey = destinationKey
}; };
try try
{ {
var response = await amazonS3.CopyObjectAsync(request, cancellationToken); var response = await amazonS3.CopyObjectAsync(request, cancellationToken);
logger.LogInformation("Successfully copied file from S3 with bucket name {SourceBucketName} and key name {SourceKeyName} to bucket name {DestinationBucketName} and key name {DestinationKeyName}", logger.LogInformation("Successfully copied file from S3 with bucket={SourceBucket} and key={SourceKey} to bucket={DestinationBucket} and key={DestinationKey}",
sourceBucketName, sourceKeyName, destinationBucketName, destinationKeyName); sourceBucket, sourceKey, destinationBucket, destinationKey);
return Result.Success(); return Result.Success();
} }
catch (Exception exception) catch (Exception exception)
{ {
logger.LogError(exception, "Failed to copy file from S3 with bucket name {SourceBucketName} and key name {SourceKeyName} to bucket name {DestinationBucketName} and key name {DestinationKeyName}", logger.LogError(exception, "Failed to copy file from S3 with bucket={SourceBucket} and key={SourceKey} to bucket={DestinationBucket} and key={DestinationKey}",
sourceBucketName, sourceKeyName, destinationBucketName, destinationKeyName); sourceBucket, sourceKey, destinationBucket, destinationKey);
return Result.Error($"Failed to copy file from S3 with bucket name {sourceBucketName} and key name {sourceKeyName} to bucket name {destinationBucketName} and key name {destinationKeyName}"); return Result.Error($"Failed to copy file from S3 with bucket: {sourceBucket} and key: {sourceKey} to bucket: {destinationBucket} and key: {destinationKey}");
} }
} }
} }