From 6e469dbb4ab0dca6bfc7193ec2fee59b92a63cd8 Mon Sep 17 00:00:00 2001 From: XShine555 Date: Sun, 5 Jul 2026 04:05:43 +0200 Subject: [PATCH] refactor: replace Ardalis.Result with ErrorOr across the app Ardalis Result carried incoherent success sub-statuses and a clunky generic converter; ErrorOr models success-or-errors cleanly. - Application: all commands/queries/handlers now return ErrorOr (non-generic Result -> ErrorOr); errors via Error.NotFound/ Conflict/Validation/Unauthorized/Failure; success via value or new Success() - Drop ResultExtensions.As<>(): error propagation is now just return .Errors - Rewrite HTTP mapping (ErrorOrHttpExtensions) off Error.Type; success maps to 200 (value) or 204 (Success); Created still built in the endpoints - Endpoints/gateway middleware: !IsSuccess -> IsError - Swap Ardalis.Result package for ErrorOr 2.1.1 (remove unused ref from Worker) Build: 0 warnings, 0 errors. Co-Authored-By: Claude Opus 4.8 --- backend/Directory.Packages.props | 2 +- .../Musify.Api/Endpoints/PlayListEndpoints.cs | 2 +- .../Musify.Api/Endpoints/TrackEndpoints.cs | 2 +- backend/Musify.Api/Endpoints/UserEndpoints.cs | 2 +- .../Extensions/ErrorOrHttpExtensions.cs | 38 +++++++++++++++++++ .../Extensions/ResultHttpExtensions.cs | 36 ------------------ backend/Musify.Api/Musify.Api.csproj | 2 +- .../Extensions/ResultExtensions.cs | 25 ------------ .../Musify.Application.csproj | 2 +- .../Commands/AddTrackToPlayListCommand.cs | 4 +- .../Commands/CreatePlayListCommand.cs | 4 +- .../Commands/DeletePlayListCommand.cs | 4 +- .../RemoveTrackFromPlayListCommand.cs | 4 +- .../RequestPlayListPictureUploadCommand.cs | 4 +- .../Commands/UpdatePlayListCommand.cs | 4 +- .../AddTrackToPlayListCommandHandler.cs | 16 ++++---- .../Handlers/CreatePlayListCommandHandler.cs | 27 +++++++------ .../Handlers/DeletePlayListCommandHandler.cs | 16 ++++---- .../Handlers/GetPlayListByIdQueryHandler.cs | 13 ++++--- .../Handlers/GetPlayListTracksQueryHandler.cs | 10 ++--- .../GetPlayListsByUserIdQueryHandler.cs | 8 ++-- .../Handlers/GetPlayListsQueryHandler.cs | 8 ++-- .../RemoveTrackFromPlayListCommandHandler.cs | 14 +++---- ...uestPlayListPictureUploadCommandHandler.cs | 18 ++++----- .../Handlers/UpdatePlayListCommandHandler.cs | 29 +++++++------- .../PlayLists/Queries/GetPlayListByIdQuery.cs | 4 +- .../Queries/GetPlayListTracksQuery.cs | 4 +- .../Queries/GetPlayListsByUserIdQuery.cs | 4 +- .../PlayLists/Queries/GetPlayListsQuery.cs | 4 +- .../Services/UploadIntentValidator.cs | 24 ++++++------ .../Tracks/Commands/CreateTrackCommand.cs | 4 +- .../Tracks/Commands/DeleteTrackCommand.cs | 4 +- .../Commands/RequestTrackUploadUrlsCommand.cs | 4 +- .../Handlers/CreateTrackCommandHandler.cs | 23 ++++++----- .../Handlers/DeleteTrackCommandHandler.cs | 18 ++++----- .../Handlers/GetTrackByIdQueryHandler.cs | 13 ++++--- .../Handlers/GetTrackStreamQueryHandler.cs | 12 +++--- .../Handlers/GetTracksByUserIdQueryHandler.cs | 8 ++-- .../Tracks/Handlers/GetTracksQueryHandler.cs | 8 ++-- .../RequestTrackUploadUrlsCommandHandler.cs | 18 ++++----- .../Tracks/Queries/GetTrackByIdQuery.cs | 4 +- .../Tracks/Queries/GetTrackStreamQuery.cs | 4 +- .../Tracks/Queries/GetTracksByUserIdQuery.cs | 4 +- .../Tracks/Queries/GetTracksQuery.cs | 4 +- .../Users/Commands/CreateUserCommand.cs | 4 +- .../Users/Commands/SyncUserCommand.cs | 4 +- .../Handlers/CreateUserCommandHandler.cs | 12 +++--- .../Users/Handlers/GetUserByIdQueryHandler.cs | 13 ++++--- .../Users/Handlers/GetUsersQueryHandler.cs | 8 ++-- .../Users/Handlers/SyncUserCommandHandler.cs | 10 ++--- .../Users/Queries/GetUserByIdQuery.cs | 4 +- .../Users/Queries/GetUsersQuery.cs | 4 +- .../Authentication/TicketValidator.cs | 16 ++++---- .../Middleware/TicketValidationMiddleware.cs | 2 +- .../Musify.StreamingGateway.csproj | 2 +- backend/Musify.Worker/Musify.Worker.csproj | 1 - 56 files changed, 259 insertions(+), 283 deletions(-) create mode 100644 backend/Musify.Api/Extensions/ErrorOrHttpExtensions.cs delete mode 100644 backend/Musify.Api/Extensions/ResultHttpExtensions.cs delete mode 100644 backend/Musify.Application/Extensions/ResultExtensions.cs diff --git a/backend/Directory.Packages.props b/backend/Directory.Packages.props index 73422ec..2e34c09 100644 --- a/backend/Directory.Packages.props +++ b/backend/Directory.Packages.props @@ -5,9 +5,9 @@ - + diff --git a/backend/Musify.Api/Endpoints/PlayListEndpoints.cs b/backend/Musify.Api/Endpoints/PlayListEndpoints.cs index c17400f..79b26c6 100644 --- a/backend/Musify.Api/Endpoints/PlayListEndpoints.cs +++ b/backend/Musify.Api/Endpoints/PlayListEndpoints.cs @@ -119,7 +119,7 @@ public static class PlayListEndpoints new CreatePlayListCommand(currentUser.RequiredId, request.Name, request.Description, request.PictureIntentId), cancellationToken); - if (!result.IsSuccess) + if (result.IsError) return result.ToHttpResult(); return Results.Created($"/playlists/{result.Value.Id}", result.Value); diff --git a/backend/Musify.Api/Endpoints/TrackEndpoints.cs b/backend/Musify.Api/Endpoints/TrackEndpoints.cs index 382ab97..a55ff35 100644 --- a/backend/Musify.Api/Endpoints/TrackEndpoints.cs +++ b/backend/Musify.Api/Endpoints/TrackEndpoints.cs @@ -103,7 +103,7 @@ public static class TrackEndpoints new CreateTrackCommand(currentUser.RequiredId, request.Title, request.PictureIntentId, request.AudioIntentId), cancellationToken); - if (!result.IsSuccess) + if (result.IsError) return result.ToHttpResult(); return Results.Created($"/tracks/{result.Value.Id}", result.Value); diff --git a/backend/Musify.Api/Endpoints/UserEndpoints.cs b/backend/Musify.Api/Endpoints/UserEndpoints.cs index e1715f3..cf27b01 100644 --- a/backend/Musify.Api/Endpoints/UserEndpoints.cs +++ b/backend/Musify.Api/Endpoints/UserEndpoints.cs @@ -59,7 +59,7 @@ public static class UserEndpoints new CreateUserCommand(request.Id, request.Name, request.FirstName, request.SecondName), cancellationToken); - if (!result.IsSuccess) + if (result.IsError) return result.ToHttpResult(); return Results.Created($"/users/{result.Value.Id}", result.Value); diff --git a/backend/Musify.Api/Extensions/ErrorOrHttpExtensions.cs b/backend/Musify.Api/Extensions/ErrorOrHttpExtensions.cs new file mode 100644 index 0000000..f4e5133 --- /dev/null +++ b/backend/Musify.Api/Extensions/ErrorOrHttpExtensions.cs @@ -0,0 +1,38 @@ +using ErrorOr; +using IResult = Microsoft.AspNetCore.Http.IResult; + +namespace Musify.Api.Extensions; + +public static class ErrorOrHttpExtensions +{ + public static IResult ToHttpResult(this ErrorOr result) + { + if (result.IsError) + return Problem(result.Errors); + + return result.Value is Success + ? Results.NoContent() + : Results.Ok(result.Value); + } + + private static IResult Problem(List errors) + { + if (errors.All(e => e.Type == ErrorType.Validation)) + return Results.ValidationProblem(ToValidationDictionary(errors)); + + var error = errors[0]; + return error.Type switch + { + ErrorType.NotFound => Results.NotFound(error.Description), + ErrorType.Unauthorized => Results.Unauthorized(), + ErrorType.Forbidden => Results.StatusCode(StatusCodes.Status403Forbidden), + ErrorType.Conflict => Results.Conflict(error.Description), + _ => Results.Problem(error.Description) + }; + } + + private static Dictionary ToValidationDictionary(IEnumerable errors) => + errors + .GroupBy(e => string.IsNullOrEmpty(e.Code) ? "general" : e.Code) + .ToDictionary(g => g.Key, g => g.Select(e => e.Description).ToArray()); +} diff --git a/backend/Musify.Api/Extensions/ResultHttpExtensions.cs b/backend/Musify.Api/Extensions/ResultHttpExtensions.cs deleted file mode 100644 index 02ad993..0000000 --- a/backend/Musify.Api/Extensions/ResultHttpExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Ardalis.Result; -using IResult = Microsoft.AspNetCore.Http.IResult; - -namespace Musify.Api.Extensions; - -public static class ResultHttpExtensions -{ - public static IResult ToHttpResult(this Result result) => - result.Status switch - { - ResultStatus.Ok or ResultStatus.NoContent => Results.NoContent(), - ResultStatus.NotFound => Results.NotFound(result.Errors.FirstOrDefault()), - ResultStatus.Invalid => Results.ValidationProblem(ToValidationDictionary(result.ValidationErrors)), - ResultStatus.Unauthorized => Results.Unauthorized(), - ResultStatus.Forbidden => Results.StatusCode(StatusCodes.Status403Forbidden), - ResultStatus.Conflict => Results.Conflict(result.Errors.FirstOrDefault()), - _ => Results.Problem(string.Join(", ", result.Errors)) - }; - - public static IResult ToHttpResult(this Result result) => - result.Status switch - { - ResultStatus.Ok => Results.Ok(result.Value), - ResultStatus.NotFound => Results.NotFound(result.Errors.FirstOrDefault()), - ResultStatus.Invalid => Results.ValidationProblem(ToValidationDictionary(result.ValidationErrors)), - ResultStatus.Unauthorized => Results.Unauthorized(), - ResultStatus.Forbidden => Results.StatusCode(StatusCodes.Status403Forbidden), - ResultStatus.Conflict => Results.Conflict(result.Errors.FirstOrDefault()), - _ => Results.Problem(string.Join(", ", result.Errors)) - }; - - private static Dictionary ToValidationDictionary(IEnumerable errors) => - errors - .GroupBy(e => string.IsNullOrEmpty(e.Identifier) ? "general" : e.Identifier) - .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); -} diff --git a/backend/Musify.Api/Musify.Api.csproj b/backend/Musify.Api/Musify.Api.csproj index 0c795d1..f9cb76c 100644 --- a/backend/Musify.Api/Musify.Api.csproj +++ b/backend/Musify.Api/Musify.Api.csproj @@ -5,7 +5,7 @@ - + diff --git a/backend/Musify.Application/Extensions/ResultExtensions.cs b/backend/Musify.Application/Extensions/ResultExtensions.cs deleted file mode 100644 index 04bf866..0000000 --- a/backend/Musify.Application/Extensions/ResultExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Ardalis.Result; - -namespace Musify.Application.Extensions; - -public static class ResultExtensions -{ - public static Result As(this Result result) - { - return result.Status switch - { - ResultStatus.Ok or - ResultStatus.Created or - ResultStatus.NoContent => throw new InvalidOperationException($"Cannot convert a successful result ( {result.Status} ) to another type. Use Map or Bind instead."), - ResultStatus.NotFound => Result.NotFound(result.Errors.ToArray()), - ResultStatus.Forbidden => Result.Forbidden(result.Errors.ToArray()), - ResultStatus.Unauthorized => Result.Unauthorized(result.Errors.ToArray()), - ResultStatus.Invalid => Result.Invalid(result.ValidationErrors.ToArray()), - ResultStatus.Conflict => Result.Conflict(result.Errors.ToArray()), - ResultStatus.CriticalError => Result.CriticalError(result.Errors.ToArray()), - ResultStatus.Unavailable => Result.Unavailable(result.Errors.ToArray()), - ResultStatus.Error => Result.Error(string.Join(";", result.Errors)), - _ => Result.Error(string.Join(";", result.Errors)) - }; - } -} \ No newline at end of file diff --git a/backend/Musify.Application/Musify.Application.csproj b/backend/Musify.Application/Musify.Application.csproj index 5e4de3b..e6266ce 100644 --- a/backend/Musify.Application/Musify.Application.csproj +++ b/backend/Musify.Application/Musify.Application.csproj @@ -1,7 +1,7 @@ - + diff --git a/backend/Musify.Application/PlayLists/Commands/AddTrackToPlayListCommand.cs b/backend/Musify.Application/PlayLists/Commands/AddTrackToPlayListCommand.cs index 3d5e96b..430c3e0 100644 --- a/backend/Musify.Application/PlayLists/Commands/AddTrackToPlayListCommand.cs +++ b/backend/Musify.Application/PlayLists/Commands/AddTrackToPlayListCommand.cs @@ -1,8 +1,8 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; namespace Musify.Application.PlayLists.Commands { public record AddTrackToPlayListCommand(long UserId, Guid PlayListId, Guid TrackId) - : ICommand; + : ICommand>; } diff --git a/backend/Musify.Application/PlayLists/Commands/CreatePlayListCommand.cs b/backend/Musify.Application/PlayLists/Commands/CreatePlayListCommand.cs index 95b3788..2b6e5b2 100644 --- a/backend/Musify.Application/PlayLists/Commands/CreatePlayListCommand.cs +++ b/backend/Musify.Application/PlayLists/Commands/CreatePlayListCommand.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.PlayLists.Responses; @@ -9,5 +9,5 @@ namespace Musify.Application.PlayLists.Commands string Name, string Description, Guid? PictureIntentId) - : ICommand>; + : ICommand>; } diff --git a/backend/Musify.Application/PlayLists/Commands/DeletePlayListCommand.cs b/backend/Musify.Application/PlayLists/Commands/DeletePlayListCommand.cs index c1860c5..3360559 100644 --- a/backend/Musify.Application/PlayLists/Commands/DeletePlayListCommand.cs +++ b/backend/Musify.Application/PlayLists/Commands/DeletePlayListCommand.cs @@ -1,8 +1,8 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; namespace Musify.Application.PlayLists.Commands { public record DeletePlayListCommand(long UserId, Guid PlayListId) - : ICommand; + : ICommand>; } \ No newline at end of file diff --git a/backend/Musify.Application/PlayLists/Commands/RemoveTrackFromPlayListCommand.cs b/backend/Musify.Application/PlayLists/Commands/RemoveTrackFromPlayListCommand.cs index 991267d..f5f6e96 100644 --- a/backend/Musify.Application/PlayLists/Commands/RemoveTrackFromPlayListCommand.cs +++ b/backend/Musify.Application/PlayLists/Commands/RemoveTrackFromPlayListCommand.cs @@ -1,8 +1,8 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; namespace Musify.Application.PlayLists.Commands { public record RemoveTrackFromPlayListCommand(long UserId, Guid PlayListId, Guid TrackId) - : ICommand; + : ICommand>; } diff --git a/backend/Musify.Application/PlayLists/Commands/RequestPlayListPictureUploadCommand.cs b/backend/Musify.Application/PlayLists/Commands/RequestPlayListPictureUploadCommand.cs index 7f8a827..3aa40e6 100644 --- a/backend/Musify.Application/PlayLists/Commands/RequestPlayListPictureUploadCommand.cs +++ b/backend/Musify.Application/PlayLists/Commands/RequestPlayListPictureUploadCommand.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.PlayLists.Responses; @@ -9,5 +9,5 @@ namespace Musify.Application.PlayLists.Commands string FileType, string ContentType, long? ExpectedSizeBytes = null) - : ICommand>; + : ICommand>; } diff --git a/backend/Musify.Application/PlayLists/Commands/UpdatePlayListCommand.cs b/backend/Musify.Application/PlayLists/Commands/UpdatePlayListCommand.cs index a2bfe18..c715408 100644 --- a/backend/Musify.Application/PlayLists/Commands/UpdatePlayListCommand.cs +++ b/backend/Musify.Application/PlayLists/Commands/UpdatePlayListCommand.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.PlayLists.Responses; @@ -10,5 +10,5 @@ namespace Musify.Application.PlayLists.Commands string? NewName, string? NewDescription, Guid? NewPictureIntentId) - : ICommand>; + : ICommand>; } diff --git a/backend/Musify.Application/PlayLists/Handlers/AddTrackToPlayListCommandHandler.cs b/backend/Musify.Application/PlayLists/Handlers/AddTrackToPlayListCommandHandler.cs index c078f9f..c2af69e 100644 --- a/backend/Musify.Application/PlayLists/Handlers/AddTrackToPlayListCommandHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/AddTrackToPlayListCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -11,22 +11,22 @@ namespace Musify.Application.PlayLists.Handlers public class AddTrackToPlayListCommandHandler( IDatabase database, ILogger logger) - : ICommandHandler + : ICommandHandler> { - public async ValueTask Handle(AddTrackToPlayListCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(AddTrackToPlayListCommand request, CancellationToken cancellationToken) { var playList = await database.PlayLists .SingleOrDefaultAsync(pl => pl.Id == request.PlayListId, cancellationToken); if (playList is null) { logger.LogInformation("Playlist {PlayListId} not found", request.PlayListId); - return Result.NotFound(); + return Error.NotFound(); } if (playList.UserId != request.UserId) { logger.LogWarning("User {UserId} is not the owner of playlist {PlayListId}", request.UserId, request.PlayListId); - return Result.Unauthorized(); + return Error.Unauthorized(); } var trackExists = await database.Tracks @@ -35,7 +35,7 @@ namespace Musify.Application.PlayLists.Handlers if (!trackExists) { logger.LogInformation("Track {TrackId} not found", request.TrackId); - return Result.NotFound($"Track {request.TrackId} not found"); + return Error.NotFound(description: $"Track {request.TrackId} not found"); } var alreadyAdded = await database.PlayListHasTracks @@ -44,7 +44,7 @@ namespace Musify.Application.PlayLists.Handlers if (alreadyAdded) { logger.LogInformation("Track {TrackId} already in playlist {PlayListId}", request.TrackId, request.PlayListId); - return Result.Conflict("Track is already in the playlist."); + return Error.Conflict(description: "Track is already in the playlist."); } var nextPosition = await database.PlayListHasTracks @@ -64,7 +64,7 @@ namespace Musify.Application.PlayLists.Handlers logger.LogInformation("Added track {TrackId} to playlist {PlayListId} at position {Position}", request.TrackId, request.PlayListId, nextPosition); - return Result.Success(); + return new Success(); } } } diff --git a/backend/Musify.Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs b/backend/Musify.Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs index 9405a36..c71acbe 100644 --- a/backend/Musify.Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/CreatePlayListCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -7,7 +7,6 @@ using Musify.Application.Shared; using Musify.Application.Events; using Musify.Application.PlayLists.Commands; using Musify.Application.PlayLists.Responses; -using Musify.Application.Extensions; using Musify.Application.Services; using Musify.Domain.Entities; using Musify.Application.Contracts; @@ -22,9 +21,9 @@ namespace Musify.Application.PlayLists.Handlers ApplicationStorageConfiguration storageConfiguration, PlayListConfiguration playListConfiguration, UploadIntentConfiguration uploadIntentConfiguration) - : ICommandHandler> + : ICommandHandler> { - public async ValueTask> Handle(CreatePlayListCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(CreatePlayListCommand request, CancellationToken cancellationToken) { var userExists = await database.Users .AsNoTracking() @@ -32,7 +31,7 @@ namespace Musify.Application.PlayLists.Handlers if (!userExists) { logger.LogWarning("User {UserId} not found", request.UserId); - return Result.NotFound($"User {request.UserId} not found"); + return Error.NotFound(description: $"User {request.UserId} not found"); } UploadIntent? pictureIntent = null; @@ -43,8 +42,8 @@ namespace Musify.Application.PlayLists.Handlers var validation = await uploadIntentValidator.ValidateAndLoadAsync( uploadIntentConfiguration, request.PictureIntentId.Value, request.UserId, cancellationToken); - if (!validation.IsSuccess) - return validation.As(); + if (validation.IsError) + return validation.Errors; pictureIntent = validation.Value; originalPictureName = pictureIntent.ObjectName; @@ -73,8 +72,8 @@ namespace Musify.Application.PlayLists.Handlers var finalPictureKey = playListConfiguration.Routes.BuildOriginalPicturePath(request.UserId, originalPictureName); var publishResult = await PublishCreatePlayListEventAsync( playList.Id, pictureIntent, finalPictureKey, cancellationToken); - if (!publishResult.IsSuccess) - return publishResult; + if (publishResult.IsError) + return publishResult.Errors; } try @@ -84,14 +83,14 @@ namespace Musify.Application.PlayLists.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to save playlist for user {UserId}", request.UserId); - return Result.Error($"Failed to create playlist for user {request.UserId}"); + return Error.Failure(description: $"Failed to create playlist for user {request.UserId}"); } logger.LogInformation("Created playlist {PlayListId} for user {UserId}", playList.Id, request.UserId); - return Result.Created(PlayListApplicationResponse.FromEntity(playList)); + return PlayListApplicationResponse.FromEntity(playList); } - async Task> PublishCreatePlayListEventAsync( + async Task> PublishCreatePlayListEventAsync( Guid playListId, UploadIntent pictureIntent, string finalPictureKey, @@ -119,12 +118,12 @@ namespace Musify.Application.PlayLists.Handlers playListConfiguration.PicturesSizes.LargePictureWidth, playListConfiguration.PicturesSizes.LargePictureHeight)), cancellationToken); - return Result.Success(); + return new Success(); } catch (Exception exception) { logger.LogError(exception, "Failed to publish create playlist event for playlist {PlayListId}", playListId); - return Result.Error($"Failed to publish create playlist event for playlist {playListId}"); + return Error.Failure(description: $"Failed to publish create playlist event for playlist {playListId}"); } } } diff --git a/backend/Musify.Application/PlayLists/Handlers/DeletePlayListCommandHandler.cs b/backend/Musify.Application/PlayLists/Handlers/DeletePlayListCommandHandler.cs index 459066f..5fbf156 100644 --- a/backend/Musify.Application/PlayLists/Handlers/DeletePlayListCommandHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/DeletePlayListCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -13,21 +13,21 @@ namespace Musify.Application.PlayLists.Handlers IDatabase database, IEventBus eventBus, ILogger logger) - : ICommandHandler + : ICommandHandler> { - public async ValueTask Handle(DeletePlayListCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(DeletePlayListCommand request, CancellationToken cancellationToken) { var playList = await database.PlayLists.SingleOrDefaultAsync(p => p.Id == request.PlayListId, cancellationToken); if (playList is null) { logger.LogDebug("Playlist {PlayListId} not found", request.PlayListId); - return Result.NotFound(); + return Error.NotFound(); } if (playList.UserId != request.UserId) { logger.LogWarning("Playlist {PlayListId} does not belong to user {UserId}", request.PlayListId, request.UserId); - return Result.Unauthorized(); + return Error.Unauthorized(); } playList.LifeCycleStatus = LifeCycleStatus.Removing; @@ -41,7 +41,7 @@ namespace Musify.Application.PlayLists.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to publish delete playlist event for playlist {PlayListId}", request.PlayListId); - return Result.Error($"Failed to delete playlist {request.PlayListId}"); + return Error.Failure(description: $"Failed to delete playlist {request.PlayListId}"); } try @@ -51,10 +51,10 @@ namespace Musify.Application.PlayLists.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to mark playlist {PlayListId} as removing", request.PlayListId); - return Result.Error($"Failed to delete playlist {request.PlayListId}"); + return Error.Failure(description: $"Failed to delete playlist {request.PlayListId}"); } - return Result.NoContent(); + return new Success(); } } } \ No newline at end of file diff --git a/backend/Musify.Application/PlayLists/Handlers/GetPlayListByIdQueryHandler.cs b/backend/Musify.Application/PlayLists/Handlers/GetPlayListByIdQueryHandler.cs index 5fc3439..9752143 100644 --- a/backend/Musify.Application/PlayLists/Handlers/GetPlayListByIdQueryHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/GetPlayListByIdQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Microsoft.EntityFrameworkCore; using Musify.Application.PlayLists.Responses; using Musify.Application.PlayLists.Queries; @@ -8,9 +8,9 @@ using Musify.Application.Contracts; namespace Musify.Application.PlayLists.Handlers { public class GetPlayListByIdQueryHandler(IDatabase database) - : IQueryHandler> + : IQueryHandler> { - public async ValueTask> Handle(GetPlayListByIdQuery request, CancellationToken cancellationToken) + public async ValueTask> Handle(GetPlayListByIdQuery request, CancellationToken cancellationToken) { var playList = await database.PlayLists .AsNoTracking() @@ -18,9 +18,10 @@ namespace Musify.Application.PlayLists.Handlers .Select(p => PlayListApplicationResponse.FromEntity(p)) .SingleOrDefaultAsync(cancellationToken); - return playList is null - ? Result.NotFound() - : Result.Success(playList); + if (playList is null) + return Error.NotFound(); + + return playList; } } } \ No newline at end of file diff --git a/backend/Musify.Application/PlayLists/Handlers/GetPlayListTracksQueryHandler.cs b/backend/Musify.Application/PlayLists/Handlers/GetPlayListTracksQueryHandler.cs index 6f9a3eb..e46f4b0 100644 --- a/backend/Musify.Application/PlayLists/Handlers/GetPlayListTracksQueryHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/GetPlayListTracksQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts; @@ -10,15 +10,15 @@ using X.PagedList.EF; namespace Musify.Application.PlayLists.Handlers { public class GetPlayListTracksQueryHandler(IDatabase database) - : IQueryHandler> > + : IQueryHandler> > { - public async ValueTask >> Handle(GetPlayListTracksQuery request, CancellationToken cancellationToken) + public async ValueTask >> Handle(GetPlayListTracksQuery request, CancellationToken cancellationToken) { var playListExists = await database.PlayLists .AsNoTracking() .AnyAsync(p => p.Id == request.PlayListId, cancellationToken); if (!playListExists) - return Result>.NotFound(); + return Error.NotFound(); var tracksQuery = database.PlayListHasTracks .AsNoTracking() @@ -32,7 +32,7 @@ namespace Musify.Application.PlayLists.Handlers .Select(plt => TrackApplicationResponse.FromEntity(plt.Track)) .ToPagedListAsync(request.PageNumber, request.PageSize, totalCount, cancellationToken); - return Result.Success(PaginatedResponse.FromPagedList(pagedTracks)); + return PaginatedResponse.FromPagedList(pagedTracks); } } } diff --git a/backend/Musify.Application/PlayLists/Handlers/GetPlayListsByUserIdQueryHandler.cs b/backend/Musify.Application/PlayLists/Handlers/GetPlayListsByUserIdQueryHandler.cs index d4b571c..d0e44e2 100644 --- a/backend/Musify.Application/PlayLists/Handlers/GetPlayListsByUserIdQueryHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/GetPlayListsByUserIdQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Microsoft.EntityFrameworkCore; using Musify.Application.Pagination; using Musify.Application.PlayLists.Responses; @@ -10,9 +10,9 @@ using Musify.Application.Contracts; namespace Musify.Application.PlayLists.Handlers { public class GetPlayListsByUserIdQueryHandler(IDatabase database) - : IQueryHandler > > + : IQueryHandler > > { - public async ValueTask >> Handle(GetPlayListsByUserIdQuery request, CancellationToken cancellationToken) + public async ValueTask >> Handle(GetPlayListsByUserIdQuery request, CancellationToken cancellationToken) { var playListsQuery = database.PlayLists .AsNoTracking() @@ -31,7 +31,7 @@ namespace Musify.Application.PlayLists.Handlers .Select(p => PlayListApplicationResponse.FromEntity(p)) .ToPagedListAsync(request.PageNumber, request.PageSize, totalCount, cancellationToken); - return Result.Success(PaginatedResponse.FromPagedList(pagedPlayLists)); + return PaginatedResponse.FromPagedList(pagedPlayLists); } } } \ No newline at end of file diff --git a/backend/Musify.Application/PlayLists/Handlers/GetPlayListsQueryHandler.cs b/backend/Musify.Application/PlayLists/Handlers/GetPlayListsQueryHandler.cs index a2bf593..b04ccc4 100644 --- a/backend/Musify.Application/PlayLists/Handlers/GetPlayListsQueryHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/GetPlayListsQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Microsoft.EntityFrameworkCore; using Musify.Application.Pagination; using Musify.Application.PlayLists.Responses; @@ -10,9 +10,9 @@ using Musify.Application.Contracts; namespace Musify.Application.PlayLists.Handlers { public class GetPlayListsQueryHandler(IDatabase database) - : IQueryHandler >> + : IQueryHandler >> { - public async ValueTask >> Handle(GetPlayListsQuery request, CancellationToken cancellationToken) + public async ValueTask >> Handle(GetPlayListsQuery request, CancellationToken cancellationToken) { var totalCount = await database.PlayLists.CountAsync(cancellationToken); @@ -22,7 +22,7 @@ namespace Musify.Application.PlayLists.Handlers .Select(p => PlayListApplicationResponse.FromEntity(p)) .ToPagedListAsync(request.PageNumber, request.PageSize, totalCount, cancellationToken); - return Result.Success(PaginatedResponse.FromPagedList(pagedPlayLists)); + return PaginatedResponse.FromPagedList(pagedPlayLists); } } } \ No newline at end of file diff --git a/backend/Musify.Application/PlayLists/Handlers/RemoveTrackFromPlayListCommandHandler.cs b/backend/Musify.Application/PlayLists/Handlers/RemoveTrackFromPlayListCommandHandler.cs index 609ede9..940b316 100644 --- a/backend/Musify.Application/PlayLists/Handlers/RemoveTrackFromPlayListCommandHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/RemoveTrackFromPlayListCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -10,22 +10,22 @@ namespace Musify.Application.PlayLists.Handlers public class RemoveTrackFromPlayListCommandHandler( IDatabase database, ILogger logger) - : ICommandHandler + : ICommandHandler> { - public async ValueTask Handle(RemoveTrackFromPlayListCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(RemoveTrackFromPlayListCommand request, CancellationToken cancellationToken) { var playList = await database.PlayLists .SingleOrDefaultAsync(pl => pl.Id == request.PlayListId, cancellationToken); if (playList is null) { logger.LogInformation("Playlist {PlayListId} not found", request.PlayListId); - return Result.NotFound(); + return Error.NotFound(); } if (playList.UserId != request.UserId) { logger.LogWarning("User {UserId} is not the owner of playlist {PlayListId}", request.UserId, request.PlayListId); - return Result.Unauthorized(); + return Error.Unauthorized(); } var link = await database.PlayListHasTracks @@ -33,7 +33,7 @@ namespace Musify.Application.PlayLists.Handlers if (link is null) { logger.LogInformation("Track {TrackId} not in playlist {PlayListId}", request.TrackId, request.PlayListId); - return Result.NotFound("Track is not in the playlist."); + return Error.NotFound(description: "Track is not in the playlist."); } database.PlayListHasTracks.Remove(link); @@ -41,7 +41,7 @@ namespace Musify.Application.PlayLists.Handlers logger.LogInformation("Removed track {TrackId} from playlist {PlayListId}", request.TrackId, request.PlayListId); - return Result.Success(); + return new Success(); } } } diff --git a/backend/Musify.Application/PlayLists/Handlers/RequestPlayListPictureUploadCommandHandler.cs b/backend/Musify.Application/PlayLists/Handlers/RequestPlayListPictureUploadCommandHandler.cs index ff0ef0d..0e66282 100644 --- a/backend/Musify.Application/PlayLists/Handlers/RequestPlayListPictureUploadCommandHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/RequestPlayListPictureUploadCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -20,9 +20,9 @@ namespace Musify.Application.PlayLists.Handlers ApplicationStorageConfiguration storageConfiguration, PlayListConfiguration playListConfiguration, UploadIntentConfiguration uploadIntentConfiguration) - : ICommandHandler> + : ICommandHandler> { - public async ValueTask> Handle(RequestPlayListPictureUploadCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(RequestPlayListPictureUploadCommand request, CancellationToken cancellationToken) { var userExists = await database.Users .AsNoTracking() @@ -30,7 +30,7 @@ namespace Musify.Application.PlayLists.Handlers if (!userExists) { logger.LogWarning("User {UserId} not found", request.UserId); - return Result.NotFound($"User {request.UserId} not found"); + return Error.NotFound(description: $"User {request.UserId} not found"); } var effectiveSizeBytes = request.ExpectedSizeBytes @@ -56,10 +56,10 @@ namespace Musify.Application.PlayLists.Handlers var quotaCheck = await uploadIntentValidator.CheckQuotaAsync( uploadIntentConfiguration, request.UserId, effectiveSizeBytes, 1, cancellationToken); - if (!quotaCheck.IsSuccess) + if (quotaCheck.IsError) { logger.LogWarning("User {UserId} failed upload intent quota check", request.UserId); - return quotaCheck; + return quotaCheck.Errors; } var intent = new UploadIntent @@ -80,19 +80,19 @@ namespace Musify.Application.PlayLists.Handlers logger.LogInformation("Issued upload intent {IntentId} for user {UserId} (PlayListPicture, temp key: {Key})", intent.Id, request.UserId, tempKey); - return Result.Success(new PlayListPictureUploadResponse( + return new PlayListPictureUploadResponse( intent.Id, storageConfiguration.Bucket, tempKey, objectName, request.ContentType, uploadIntentConfiguration.UploadUrlExpiresInSeconds, - uploadUrl)); + uploadUrl); } catch (Exception exception) { logger.LogError(exception, "Failed to generate playlist picture upload URL for user {UserId}", request.UserId); - return Result.Error("Failed to generate upload URL"); + return Error.Failure(description: "Failed to generate upload URL"); } } } diff --git a/backend/Musify.Application/PlayLists/Handlers/UpdatePlayListCommandHandler.cs b/backend/Musify.Application/PlayLists/Handlers/UpdatePlayListCommandHandler.cs index e8b9317..be4bf08 100644 --- a/backend/Musify.Application/PlayLists/Handlers/UpdatePlayListCommandHandler.cs +++ b/backend/Musify.Application/PlayLists/Handlers/UpdatePlayListCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -7,7 +7,6 @@ using Musify.Application.Shared; using Musify.Application.Events; using Musify.Application.PlayLists.Commands; using Musify.Application.PlayLists.Responses; -using Musify.Application.Extensions; using Musify.Application.Services; using Musify.Domain.Entities; using Musify.Application.Contracts; @@ -22,21 +21,21 @@ namespace Musify.Application.PlayLists.Handlers ApplicationStorageConfiguration storageConfiguration, PlayListConfiguration playListConfiguration, UploadIntentConfiguration uploadIntentConfiguration) - : ICommandHandler> + : ICommandHandler> { - public async ValueTask> Handle(UpdatePlayListCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(UpdatePlayListCommand request, CancellationToken cancellationToken) { var playListEntity = await database.PlayLists.SingleOrDefaultAsync(pl => pl.Id == request.PlayListId, cancellationToken); if (playListEntity is null) { logger.LogInformation("Playlist {PlayListId} not found", request.PlayListId); - return Result.NotFound(); + return Error.NotFound(); } if (playListEntity.UserId != request.UserId) { logger.LogWarning("User {UserId} is not the owner of playlist {PlayListId}", request.UserId, request.PlayListId); - return Result.Unauthorized(); + return Error.Unauthorized(); } if (request.NewName is not null) @@ -58,8 +57,8 @@ namespace Musify.Application.PlayLists.Handlers var validation = await uploadIntentValidator.ValidateAndLoadAsync( uploadIntentConfiguration, request.NewPictureIntentId.Value, request.UserId, cancellationToken); - if (!validation.IsSuccess) - return validation.As(); + if (validation.IsError) + return validation.Errors; pictureIntent = validation.Value; playListEntity.OriginalPictureName = pictureIntent.ObjectName; @@ -72,8 +71,8 @@ namespace Musify.Application.PlayLists.Handlers { var publishResult = await PublishUpdatePlayListPictureSourceEventAsync( playListEntity.Id, pictureIntent, finalPictureKey, cancellationToken); - if (!publishResult.IsSuccess) - return publishResult; + if (publishResult.IsError) + return publishResult.Errors; } try @@ -83,14 +82,14 @@ namespace Musify.Application.PlayLists.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to update playlist {PlayListId}", playListEntity.Id); - return Result.Error($"Failed to update playlist {playListEntity.Id}"); + return Error.Failure(description: $"Failed to update playlist {playListEntity.Id}"); } logger.LogInformation("Updated playlist {PlayListId}", playListEntity.Id); - return Result.Success(PlayListApplicationResponse.FromEntity(playListEntity)); + return PlayListApplicationResponse.FromEntity(playListEntity); } - async Task> PublishUpdatePlayListPictureSourceEventAsync( + async Task> PublishUpdatePlayListPictureSourceEventAsync( Guid playListId, UploadIntent pictureIntent, string finalPictureKey, @@ -118,12 +117,12 @@ namespace Musify.Application.PlayLists.Handlers playListConfiguration.PicturesSizes.LargePictureWidth, playListConfiguration.PicturesSizes.LargePictureHeight)), cancellationToken); - return Result.Success(); + return new Success(); } catch (Exception exception) { logger.LogError(exception, "Failed to publish update playlist picture source event for playlist {PlayListId}", playListId); - return Result.Error($"Failed to publish update playlist picture source event for playlist {playListId}"); + return Error.Failure(description: $"Failed to publish update playlist picture source event for playlist {playListId}"); } } } diff --git a/backend/Musify.Application/PlayLists/Queries/GetPlayListByIdQuery.cs b/backend/Musify.Application/PlayLists/Queries/GetPlayListByIdQuery.cs index 55d98c5..f02f40b 100644 --- a/backend/Musify.Application/PlayLists/Queries/GetPlayListByIdQuery.cs +++ b/backend/Musify.Application/PlayLists/Queries/GetPlayListByIdQuery.cs @@ -1,9 +1,9 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.PlayLists.Responses; namespace Musify.Application.PlayLists.Queries { public record GetPlayListByIdQuery(Guid Id) - : IQuery>; + : IQuery>; } \ No newline at end of file diff --git a/backend/Musify.Application/PlayLists/Queries/GetPlayListTracksQuery.cs b/backend/Musify.Application/PlayLists/Queries/GetPlayListTracksQuery.cs index 49759ef..f3f78ed 100644 --- a/backend/Musify.Application/PlayLists/Queries/GetPlayListTracksQuery.cs +++ b/backend/Musify.Application/PlayLists/Queries/GetPlayListTracksQuery.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Pagination; using Musify.Application.Tracks.Responses; @@ -9,5 +9,5 @@ namespace Musify.Application.PlayLists.Queries Guid PlayListId, int PageNumber = 1, int PageSize = 10) - : IQuery>>; + : IQuery>>; } diff --git a/backend/Musify.Application/PlayLists/Queries/GetPlayListsByUserIdQuery.cs b/backend/Musify.Application/PlayLists/Queries/GetPlayListsByUserIdQuery.cs index 1c28036..91390a0 100644 --- a/backend/Musify.Application/PlayLists/Queries/GetPlayListsByUserIdQuery.cs +++ b/backend/Musify.Application/PlayLists/Queries/GetPlayListsByUserIdQuery.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Pagination; using Musify.Application.PlayLists.Responses; @@ -10,5 +10,5 @@ namespace Musify.Application.PlayLists.Queries string? Name, int PageNumber = 1, int PageSize = 10) - : IQuery> >; + : IQuery> >; } \ No newline at end of file diff --git a/backend/Musify.Application/PlayLists/Queries/GetPlayListsQuery.cs b/backend/Musify.Application/PlayLists/Queries/GetPlayListsQuery.cs index 18d7b44..16b2890 100644 --- a/backend/Musify.Application/PlayLists/Queries/GetPlayListsQuery.cs +++ b/backend/Musify.Application/PlayLists/Queries/GetPlayListsQuery.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Pagination; using Musify.Application.PlayLists.Responses; @@ -6,5 +6,5 @@ using Musify.Application.PlayLists.Responses; namespace Musify.Application.PlayLists.Queries { public record GetPlayListsQuery(int PageNumber = 1, int PageSize = 10) - : IQuery> >; + : IQuery> >; } \ No newline at end of file diff --git a/backend/Musify.Application/Services/UploadIntentValidator.cs b/backend/Musify.Application/Services/UploadIntentValidator.cs index c3efaa5..239b9c1 100644 --- a/backend/Musify.Application/Services/UploadIntentValidator.cs +++ b/backend/Musify.Application/Services/UploadIntentValidator.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Microsoft.EntityFrameworkCore; using Musify.Application.Configuration; using Musify.Domain.Entities; @@ -11,7 +11,7 @@ public sealed class UploadIntentValidator( IDatabase database, IStorageService storageService) { - public async Task CheckQuotaAsync( + public async Task> CheckQuotaAsync( UploadIntentConfiguration config, long userId, long requiredBytes, @@ -24,16 +24,16 @@ public sealed class UploadIntentValidator( .ToListAsync(cancellationToken); if (activeIntents.Count + requiredIntentCount > config.MaxActiveUploadIntentsPerUser) - return Result.Invalid(new ValidationError("Upload intent limit exceeded. Wait for existing uploads to complete or expire.")); + return Error.Validation(description: "Upload intent limit exceeded. Wait for existing uploads to complete or expire."); var activeBytes = activeIntents.Sum(i => i.ExpectedSizeBytes ?? config.DefaultExpectedPictureSizeBytes); if (activeBytes + requiredBytes > config.MaxActiveUploadBytesPerUser) - return Result.Invalid(new ValidationError("Upload byte quota exceeded. Wait for existing uploads to complete or expire.")); + return Error.Validation(description: "Upload byte quota exceeded. Wait for existing uploads to complete or expire."); - return Result.Success(); + return new Success(); } - public async Task> ValidateAndLoadAsync( + public async Task> ValidateAndLoadAsync( UploadIntentConfiguration config, Guid intentId, long userId, @@ -43,21 +43,21 @@ public sealed class UploadIntentValidator( .FirstOrDefaultAsync(i => i.Id == intentId, cancellationToken); if (intent is null || intent.UserId != userId) - return Result.NotFound("Upload intent not found or not accessible."); + return Error.NotFound(description: "Upload intent not found or not accessible."); if (intent.Status == UploadIntentStatus.Consumed) - return Result.Conflict("Upload intent has already been consumed."); + return Error.Conflict(description: "Upload intent has already been consumed."); if (intent.Status == UploadIntentStatus.Expired || intent.ExpiresAt < DateTime.UtcNow) - return Result.Invalid(new ValidationError("Upload intent has expired.")); + return Error.Validation(description: "Upload intent has expired."); var metadata = await storageService.HeadObjectAsync(intent.Bucket, intent.Key, cancellationToken); if (metadata is null) - return Result.NotFound("Uploaded object not found in storage. Upload the file first."); + return Error.NotFound(description: "Uploaded object not found in storage. Upload the file first."); if (metadata.ContentLength > config.MaxUploadBytes) - return Result.Invalid(new ValidationError($"Uploaded file exceeds the maximum allowed size of {config.MaxUploadBytes} bytes.")); + return Error.Validation(description: $"Uploaded file exceeds the maximum allowed size of {config.MaxUploadBytes} bytes."); - return Result.Success(intent); + return intent; } } diff --git a/backend/Musify.Application/Tracks/Commands/CreateTrackCommand.cs b/backend/Musify.Application/Tracks/Commands/CreateTrackCommand.cs index b5fd8a3..8f04682 100644 --- a/backend/Musify.Application/Tracks/Commands/CreateTrackCommand.cs +++ b/backend/Musify.Application/Tracks/Commands/CreateTrackCommand.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Tracks.Responses; @@ -9,5 +9,5 @@ namespace Musify.Application.Tracks.Commands string Title, Guid PictureIntentId, Guid AudioIntentId) - : ICommand>; + : ICommand>; } diff --git a/backend/Musify.Application/Tracks/Commands/DeleteTrackCommand.cs b/backend/Musify.Application/Tracks/Commands/DeleteTrackCommand.cs index 619869e..f4c1bb9 100644 --- a/backend/Musify.Application/Tracks/Commands/DeleteTrackCommand.cs +++ b/backend/Musify.Application/Tracks/Commands/DeleteTrackCommand.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; namespace Musify.Application.Tracks.Commands @@ -6,5 +6,5 @@ namespace Musify.Application.Tracks.Commands public record DeleteTrackCommand( long UserId, Guid TrackId) - : ICommand; + : ICommand>; } \ No newline at end of file diff --git a/backend/Musify.Application/Tracks/Commands/RequestTrackUploadUrlsCommand.cs b/backend/Musify.Application/Tracks/Commands/RequestTrackUploadUrlsCommand.cs index ea82fbb..33cfe1e 100644 --- a/backend/Musify.Application/Tracks/Commands/RequestTrackUploadUrlsCommand.cs +++ b/backend/Musify.Application/Tracks/Commands/RequestTrackUploadUrlsCommand.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Tracks.Responses; @@ -12,5 +12,5 @@ namespace Musify.Application.Tracks.Commands string AudioContentType, long? ExpectedPictureSizeBytes = null, long? ExpectedAudioSizeBytes = null) - : ICommand>; + : ICommand>; } diff --git a/backend/Musify.Application/Tracks/Handlers/CreateTrackCommandHandler.cs b/backend/Musify.Application/Tracks/Handlers/CreateTrackCommandHandler.cs index fcf4754..0ac3a3b 100644 --- a/backend/Musify.Application/Tracks/Handlers/CreateTrackCommandHandler.cs +++ b/backend/Musify.Application/Tracks/Handlers/CreateTrackCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -7,7 +7,6 @@ using Musify.Application.Shared; using Musify.Application.Events; using Musify.Application.Tracks.Commands; using Musify.Application.Tracks.Responses; -using Musify.Application.Extensions; using Musify.Application.Services; using Musify.Domain.Entities; using Musify.Domain.ValueObjects; @@ -23,29 +22,29 @@ namespace Musify.Application.Tracks.Handlers ApplicationStorageConfiguration storageConfiguration, TrackConfiguration trackConfiguration, UploadIntentConfiguration uploadIntentConfiguration) - : ICommandHandler> + : ICommandHandler> { - public async ValueTask> Handle(CreateTrackCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(CreateTrackCommand request, CancellationToken cancellationToken) { var userExists = await database.Users.AsNoTracking() .AnyAsync(u => u.Id == request.UserId, cancellationToken); if (!userExists) { logger.LogWarning("User {UserId} not found", request.UserId); - return Result.NotFound($"User {request.UserId} not found"); + return Error.NotFound(description: $"User {request.UserId} not found"); } var pictureValidation = await uploadIntentValidator.ValidateAndLoadAsync( uploadIntentConfiguration, request.PictureIntentId, request.UserId, cancellationToken); - if (!pictureValidation.IsSuccess) - return pictureValidation.As(); + if (pictureValidation.IsError) + return pictureValidation.Errors; var audioValidation = await uploadIntentValidator.ValidateAndLoadAsync( uploadIntentConfiguration, request.AudioIntentId, request.UserId, cancellationToken); - if (!audioValidation.IsSuccess) - return audioValidation.As(); + if (audioValidation.IsError) + return audioValidation.Errors; var pictureIntent = pictureValidation.Value; var audioIntent = audioValidation.Value; @@ -105,7 +104,7 @@ namespace Musify.Application.Tracks.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to publish create track event for track {TrackId}", trackEntity.Id); - return Result.Error($"Failed to create track for {request.Title}"); + return Error.Failure(description: $"Failed to create track for {request.Title}"); } try @@ -115,10 +114,10 @@ namespace Musify.Application.Tracks.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to save track {Title}", request.Title); - return Result.Error($"Failed to create track for {request.Title}"); + return Error.Failure(description: $"Failed to create track for {request.Title}"); } - return Result.Created(TrackApplicationResponse.FromEntity(trackEntity)); + return TrackApplicationResponse.FromEntity(trackEntity); } } } diff --git a/backend/Musify.Application/Tracks/Handlers/DeleteTrackCommandHandler.cs b/backend/Musify.Application/Tracks/Handlers/DeleteTrackCommandHandler.cs index a59e79b..345cb3a 100644 --- a/backend/Musify.Application/Tracks/Handlers/DeleteTrackCommandHandler.cs +++ b/backend/Musify.Application/Tracks/Handlers/DeleteTrackCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -13,15 +13,15 @@ namespace Musify.Application.Tracks.Handlers IDatabase database, IEventBus eventBus, ILogger logger) - : ICommandHandler + : ICommandHandler> { - public async ValueTask Handle(DeleteTrackCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(DeleteTrackCommand request, CancellationToken cancellationToken) { var track = await database.Tracks.SingleOrDefaultAsync(t => t.Id == request.TrackId, cancellationToken); if (track is null) { logger.LogInformation("Track {TrackId} not found", request.TrackId); - return Result.NotFound(); + return Error.NotFound(); } var isOwner = await database.UserHasTracks @@ -30,14 +30,14 @@ namespace Musify.Application.Tracks.Handlers if (!isOwner) { logger.LogWarning("User {UserId} unauthorized to delete track {TrackId}", request.UserId, request.TrackId); - return Result.Unauthorized(); + return Error.Unauthorized(); } if (track.AudioTranscodeProcessingStatus == ProcessingStatus.Processing || track.AudioTranscodeProcessingStatus == ProcessingStatus.Pending) { logger.LogWarning("Track {TrackId} is currently being processed and cannot be deleted", request.TrackId); - return Result.Conflict("Track is currently being processed and cannot be deleted"); + return Error.Conflict(description: "Track is currently being processed and cannot be deleted"); } track.LifeCycleStatus = LifeCycleStatus.Removing; @@ -51,7 +51,7 @@ namespace Musify.Application.Tracks.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to publish delete track event for track {TrackId}", request.TrackId); - return Result.Error($"Failed to delete track {request.TrackId}"); + return Error.Failure(description: $"Failed to delete track {request.TrackId}"); } try @@ -61,10 +61,10 @@ namespace Musify.Application.Tracks.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to mark track {TrackId} as processing before deletion", request.TrackId); - return Result.Error($"Failed to delete track {request.TrackId}"); + return Error.Failure(description: $"Failed to delete track {request.TrackId}"); } - return Result.NoContent(); + return new Success(); } } } \ No newline at end of file diff --git a/backend/Musify.Application/Tracks/Handlers/GetTrackByIdQueryHandler.cs b/backend/Musify.Application/Tracks/Handlers/GetTrackByIdQueryHandler.cs index 8fa199b..62b8ac0 100644 --- a/backend/Musify.Application/Tracks/Handlers/GetTrackByIdQueryHandler.cs +++ b/backend/Musify.Application/Tracks/Handlers/GetTrackByIdQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts; @@ -8,18 +8,19 @@ using Musify.Application.Tracks.Responses; namespace Musify.Application.Tracks.Handlers { public class GetTrackByIdQueryHandler(IDatabase database) - : IQueryHandler > + : IQueryHandler > { - public async ValueTask> Handle(GetTrackByIdQuery request, CancellationToken cancellationToken) + public async ValueTask> Handle(GetTrackByIdQuery request, CancellationToken cancellationToken) { var track = await database.Tracks.AsNoTracking() .Where(t => t.Id == request.TrackId) .Select(t => TrackApplicationResponse.FromEntity(t)) .SingleOrDefaultAsync(cancellationToken); - return track is null - ? Result.NotFound() - : Result.Success(track); + if (track is null) + return Error.NotFound(); + + return track; } } } \ No newline at end of file diff --git a/backend/Musify.Application/Tracks/Handlers/GetTrackStreamQueryHandler.cs b/backend/Musify.Application/Tracks/Handlers/GetTrackStreamQueryHandler.cs index b96925e..46016d2 100644 --- a/backend/Musify.Application/Tracks/Handlers/GetTrackStreamQueryHandler.cs +++ b/backend/Musify.Application/Tracks/Handlers/GetTrackStreamQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -16,9 +16,9 @@ namespace Musify.Application.Tracks.Handlers TrackConfiguration trackConfiguration, StreamGatewayConfiguration streamGatewayConfiguration, ILogger logger) - : IQueryHandler> + : IQueryHandler> { - public async ValueTask> Handle(GetTrackStreamQuery request, CancellationToken cancellationToken) + public async ValueTask> Handle(GetTrackStreamQuery request, CancellationToken cancellationToken) { var track = await database.Tracks.AsNoTracking() .Where(t => t.Id == request.TrackId) @@ -26,13 +26,13 @@ namespace Musify.Application.Tracks.Handlers .SingleOrDefaultAsync(cancellationToken); if (track is null) - return Result.NotFound(); + return Error.NotFound(); if (string.IsNullOrWhiteSpace(track.AudioFolderName) || track.AudioTranscodeProcessingStatus != ProcessingStatus.Completed) { logger.LogInformation("Stream requested for track {TrackId} but audio is not ready", request.TrackId); - return Result.Conflict("Track audio is not available for streaming yet."); + return Error.Conflict(description: "Track audio is not available for streaming yet."); } var folderPath = trackConfiguration.Routes.BuildProcessedAudioPath(track.AudioFolderName); @@ -48,7 +48,7 @@ namespace Musify.Application.Tracks.Handlers logger.LogInformation("Issued stream ticket for track {TrackId} to user {UserId}", request.TrackId, request.UserId); - return Result.Success(new TrackStreamResponse(manifestUrl, ticket.Token, ticket.ExpiresInSeconds)); + return new TrackStreamResponse(manifestUrl, ticket.Token, ticket.ExpiresInSeconds); } } } diff --git a/backend/Musify.Application/Tracks/Handlers/GetTracksByUserIdQueryHandler.cs b/backend/Musify.Application/Tracks/Handlers/GetTracksByUserIdQueryHandler.cs index 5822428..f6d099d 100644 --- a/backend/Musify.Application/Tracks/Handlers/GetTracksByUserIdQueryHandler.cs +++ b/backend/Musify.Application/Tracks/Handlers/GetTracksByUserIdQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Pagination; @@ -10,9 +10,9 @@ using Musify.Application.Contracts; namespace Musify.Application.Tracks.Handlers { public class GetTracksByUserIdQueryHandler(IDatabase database) - : IQueryHandler> > + : IQueryHandler> > { - public async ValueTask >> Handle(GetTracksByUserIdQuery request, CancellationToken cancellationToken) + public async ValueTask >> Handle(GetTracksByUserIdQuery request, CancellationToken cancellationToken) { var pageNumber = request.PageNumber < 1 ? 1 : request.PageNumber; var pageSize = request.PageSize < 1 ? 10 : request.PageSize; @@ -35,7 +35,7 @@ namespace Musify.Application.Tracks.Handlers .Select(t => TrackApplicationResponse.FromEntity(t.Track)) .ToPagedListAsync(pageNumber, pageSize, totalCount, cancellationToken); - return Result.Success(PaginatedResponse.FromPagedList(pagedTracks)); + return PaginatedResponse.FromPagedList(pagedTracks); } } } \ No newline at end of file diff --git a/backend/Musify.Application/Tracks/Handlers/GetTracksQueryHandler.cs b/backend/Musify.Application/Tracks/Handlers/GetTracksQueryHandler.cs index b19ebb6..ba8366a 100644 --- a/backend/Musify.Application/Tracks/Handlers/GetTracksQueryHandler.cs +++ b/backend/Musify.Application/Tracks/Handlers/GetTracksQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Pagination; @@ -10,9 +10,9 @@ using Musify.Application.Contracts; namespace Musify.Application.Tracks.Handlers { public class GetTracksQueryHandler(IDatabase database) - : IQueryHandler> > + : IQueryHandler> > { - public async ValueTask >> Handle(GetTracksQuery request, CancellationToken cancellationToken) + public async ValueTask >> Handle(GetTracksQuery request, CancellationToken cancellationToken) { var tracksQuery = database.UserHasTracks .AsNoTracking() @@ -23,7 +23,7 @@ namespace Musify.Application.Tracks.Handlers var totalCount = await tracksQuery.CountAsync(cancellationToken); var pagedTracks = await tracksQuery.ToPagedListAsync(request.PageNumber, request.PageSize, totalCount, cancellationToken); - return Result.Success(PaginatedResponse.FromPagedList(pagedTracks)); + return PaginatedResponse.FromPagedList(pagedTracks); } } } \ No newline at end of file diff --git a/backend/Musify.Application/Tracks/Handlers/RequestTrackUploadUrlsCommandHandler.cs b/backend/Musify.Application/Tracks/Handlers/RequestTrackUploadUrlsCommandHandler.cs index c651282..2e69bda 100644 --- a/backend/Musify.Application/Tracks/Handlers/RequestTrackUploadUrlsCommandHandler.cs +++ b/backend/Musify.Application/Tracks/Handlers/RequestTrackUploadUrlsCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -20,9 +20,9 @@ namespace Musify.Application.Tracks.Handlers ApplicationStorageConfiguration storageConfiguration, TrackConfiguration trackConfiguration, UploadIntentConfiguration uploadIntentConfiguration) - : ICommandHandler> + : ICommandHandler> { - public async ValueTask> Handle(RequestTrackUploadUrlsCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(RequestTrackUploadUrlsCommand request, CancellationToken cancellationToken) { var userExists = await database.Users .AsNoTracking() @@ -30,7 +30,7 @@ namespace Musify.Application.Tracks.Handlers if (!userExists) { logger.LogWarning("User {UserId} not found", request.UserId); - return Result.NotFound($"User {request.UserId} not found"); + return Error.NotFound(description: $"User {request.UserId} not found"); } var effectivePictureSize = request.ExpectedPictureSizeBytes @@ -72,10 +72,10 @@ namespace Musify.Application.Tracks.Handlers var quotaCheck = await uploadIntentValidator.CheckQuotaAsync( uploadIntentConfiguration, request.UserId, effectivePictureSize + effectiveAudioSize, 2, cancellationToken); - if (!quotaCheck.IsSuccess) + if (quotaCheck.IsError) { logger.LogWarning("User {UserId} failed upload intent quota check", request.UserId); - return quotaCheck; + return quotaCheck.Errors; } var pictureIntent = new UploadIntent @@ -110,7 +110,7 @@ namespace Musify.Application.Tracks.Handlers logger.LogInformation("Issued upload intents {PictureIntentId}/{AudioIntentId} for user {UserId} (TrackPicture/TrackAudio)", pictureIntent.Id, audioIntent.Id, request.UserId); - return Result.Success(new TrackUploadUrlsResponse( + return new TrackUploadUrlsResponse( pictureIntent.Id, audioIntent.Id, storageConfiguration.Bucket, @@ -122,12 +122,12 @@ namespace Musify.Application.Tracks.Handlers audioObjectName, request.AudioContentType, audioUploadUrl, - uploadIntentConfiguration.UploadUrlExpiresInSeconds)); + uploadIntentConfiguration.UploadUrlExpiresInSeconds); } catch (Exception exception) { logger.LogError(exception, "Failed to generate track upload URLs for user {UserId}", request.UserId); - return Result.Error("Failed to generate upload URLs"); + return Error.Failure(description: "Failed to generate upload URLs"); } } } diff --git a/backend/Musify.Application/Tracks/Queries/GetTrackByIdQuery.cs b/backend/Musify.Application/Tracks/Queries/GetTrackByIdQuery.cs index cdc3709..d7f12ab 100644 --- a/backend/Musify.Application/Tracks/Queries/GetTrackByIdQuery.cs +++ b/backend/Musify.Application/Tracks/Queries/GetTrackByIdQuery.cs @@ -1,9 +1,9 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Tracks.Responses; namespace Musify.Application.Tracks.Queries { public record GetTrackByIdQuery(Guid TrackId) - : IQuery>; + : IQuery>; } \ No newline at end of file diff --git a/backend/Musify.Application/Tracks/Queries/GetTrackStreamQuery.cs b/backend/Musify.Application/Tracks/Queries/GetTrackStreamQuery.cs index 03286ae..c2fce39 100644 --- a/backend/Musify.Application/Tracks/Queries/GetTrackStreamQuery.cs +++ b/backend/Musify.Application/Tracks/Queries/GetTrackStreamQuery.cs @@ -1,9 +1,9 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Tracks.Responses; namespace Musify.Application.Tracks.Queries { public record GetTrackStreamQuery(Guid TrackId, long UserId) - : IQuery>; + : IQuery>; } diff --git a/backend/Musify.Application/Tracks/Queries/GetTracksByUserIdQuery.cs b/backend/Musify.Application/Tracks/Queries/GetTracksByUserIdQuery.cs index 6e389dd..7ce4e3d 100644 --- a/backend/Musify.Application/Tracks/Queries/GetTracksByUserIdQuery.cs +++ b/backend/Musify.Application/Tracks/Queries/GetTracksByUserIdQuery.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Pagination; using Musify.Application.Tracks.Responses; @@ -10,5 +10,5 @@ namespace Musify.Application.Tracks.Queries string? Name = null, int PageNumber = 1, int PageSize = 10) - : IQuery > >; + : IQuery > >; } \ No newline at end of file diff --git a/backend/Musify.Application/Tracks/Queries/GetTracksQuery.cs b/backend/Musify.Application/Tracks/Queries/GetTracksQuery.cs index b483e56..f435266 100644 --- a/backend/Musify.Application/Tracks/Queries/GetTracksQuery.cs +++ b/backend/Musify.Application/Tracks/Queries/GetTracksQuery.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Pagination; using Musify.Application.Tracks.Responses; @@ -6,5 +6,5 @@ using Musify.Application.Tracks.Responses; namespace Musify.Application.Tracks.Queries { public record GetTracksQuery(int PageNumber = 1, int PageSize = 10) - : IQuery >>; + : IQuery >>; } \ No newline at end of file diff --git a/backend/Musify.Application/Users/Commands/CreateUserCommand.cs b/backend/Musify.Application/Users/Commands/CreateUserCommand.cs index 6415e31..bfcdf18 100644 --- a/backend/Musify.Application/Users/Commands/CreateUserCommand.cs +++ b/backend/Musify.Application/Users/Commands/CreateUserCommand.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Users.Responses; using Musify.Domain.Entities; @@ -9,7 +9,7 @@ namespace Musify.Application.Users.Commands string Name, string? FirstName, string? SecondName) - : ICommand> + : ICommand> { public static User ToEntity(CreateUserCommand command) { diff --git a/backend/Musify.Application/Users/Commands/SyncUserCommand.cs b/backend/Musify.Application/Users/Commands/SyncUserCommand.cs index 5419614..fc0bdc3 100644 --- a/backend/Musify.Application/Users/Commands/SyncUserCommand.cs +++ b/backend/Musify.Application/Users/Commands/SyncUserCommand.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; namespace Musify.Application.Users.Commands @@ -9,5 +9,5 @@ namespace Musify.Application.Users.Commands string? FirstName, string? SecondName, string? ProfilePictureUrl) - : ICommand; + : ICommand>; } diff --git a/backend/Musify.Application/Users/Handlers/CreateUserCommandHandler.cs b/backend/Musify.Application/Users/Handlers/CreateUserCommandHandler.cs index fabcd17..5f4d8ec 100644 --- a/backend/Musify.Application/Users/Handlers/CreateUserCommandHandler.cs +++ b/backend/Musify.Application/Users/Handlers/CreateUserCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -9,15 +9,15 @@ using Musify.Application.Users.Responses; namespace Musify.Application.Users.Handlers { public class CreateUserCommandHandler(IDatabase database, ILogger logger) - : ICommandHandler > + : ICommandHandler > { - public async ValueTask> Handle(CreateUserCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(CreateUserCommand request, CancellationToken cancellationToken) { var userExists = await database.Users.AnyAsync(u => u.Id == request.Id, cancellationToken); if (userExists) { logger.LogInformation("User {UserId} already exists", request.Id); - return Result.Conflict($"User {request.Id} already exists"); + return Error.Conflict(description: $"User {request.Id} already exists"); } var newUser = CreateUserCommand.ToEntity(request); @@ -30,11 +30,11 @@ namespace Musify.Application.Users.Handlers catch (Exception exception) { logger.LogError(exception, "Failed to create user {UserId}", request.Id); - return Result.Error($"Failed to create user {request.Id}"); + return Error.Failure(description: $"Failed to create user {request.Id}"); } logger.LogInformation("Created user {UserId}", newUser.Id); - return Result.Created(UserApplicationResponse.FromEntity(newUser)); + return UserApplicationResponse.FromEntity(newUser); } } } \ No newline at end of file diff --git a/backend/Musify.Application/Users/Handlers/GetUserByIdQueryHandler.cs b/backend/Musify.Application/Users/Handlers/GetUserByIdQueryHandler.cs index c99c799..ed6261f 100644 --- a/backend/Musify.Application/Users/Handlers/GetUserByIdQueryHandler.cs +++ b/backend/Musify.Application/Users/Handlers/GetUserByIdQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Contracts; @@ -8,9 +8,9 @@ using Musify.Application.Users.Responses; namespace Musify.Application.Users.Handlers { public class GetUserByIdQueryHandler(IDatabase database) - : IQueryHandler > + : IQueryHandler > { - public async ValueTask> Handle(GetUserByIdQuery request, CancellationToken cancellationToken) + public async ValueTask> Handle(GetUserByIdQuery request, CancellationToken cancellationToken) { var user = await database.Users .AsNoTracking() @@ -18,9 +18,10 @@ namespace Musify.Application.Users.Handlers .Select(u => UserApplicationResponse.FromEntity(u)) .SingleOrDefaultAsync(cancellationToken); - return user is null - ? Result.NotFound() - : Result.Success(user); + if (user is null) + return Error.NotFound(); + + return user; } } } \ No newline at end of file diff --git a/backend/Musify.Application/Users/Handlers/GetUsersQueryHandler.cs b/backend/Musify.Application/Users/Handlers/GetUsersQueryHandler.cs index cca1b12..06b5f7b 100644 --- a/backend/Musify.Application/Users/Handlers/GetUsersQueryHandler.cs +++ b/backend/Musify.Application/Users/Handlers/GetUsersQueryHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Musify.Application.Pagination; @@ -10,9 +10,9 @@ using Musify.Application.Contracts; namespace Musify.Application.Users.Handlers { public class GetUsersQueryHandler(IDatabase database) - : IQueryHandler > > + : IQueryHandler > > { - public async ValueTask >> Handle(GetUsersQuery request, CancellationToken cancellationToken) + public async ValueTask >> Handle(GetUsersQuery request, CancellationToken cancellationToken) { var user = database.Users .AsNoTracking() @@ -29,7 +29,7 @@ namespace Musify.Application.Users.Handlers .Select(u => UserApplicationResponse.FromEntity(u)) .ToPagedListAsync(request.PageNumber, request.PageSize, totalCount, cancellationToken); - return Result.Success(PaginatedResponse.FromPagedList(pagedUser)); + return PaginatedResponse.FromPagedList(pagedUser); } } } \ No newline at end of file diff --git a/backend/Musify.Application/Users/Handlers/SyncUserCommandHandler.cs b/backend/Musify.Application/Users/Handlers/SyncUserCommandHandler.cs index 61aabb8..0718feb 100644 --- a/backend/Musify.Application/Users/Handlers/SyncUserCommandHandler.cs +++ b/backend/Musify.Application/Users/Handlers/SyncUserCommandHandler.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; @@ -9,9 +9,9 @@ using Musify.Domain.Entities; namespace Musify.Application.Users.Handlers { public class SyncUserCommandHandler(IDatabase database, ILogger logger) - : ICommandHandler + : ICommandHandler> { - public async ValueTask Handle(SyncUserCommand request, CancellationToken cancellationToken) + public async ValueTask> Handle(SyncUserCommand request, CancellationToken cancellationToken) { var user = await database.Users .SingleOrDefaultAsync(u => u.Id == request.Id, cancellationToken); @@ -31,7 +31,7 @@ namespace Musify.Application.Users.Handlers await database.SaveChangesAsync(cancellationToken); logger.LogInformation("Provisioned user {UserId}", request.Id); - return Result.Success(); + return new Success(); } user.Name = request.Name; @@ -44,7 +44,7 @@ namespace Musify.Application.Users.Handlers if (written > 0) logger.LogInformation("Synced profile for user {UserId}", request.Id); - return Result.Success(); + return new Success(); } } } diff --git a/backend/Musify.Application/Users/Queries/GetUserByIdQuery.cs b/backend/Musify.Application/Users/Queries/GetUserByIdQuery.cs index f17c5e6..3ba862c 100644 --- a/backend/Musify.Application/Users/Queries/GetUserByIdQuery.cs +++ b/backend/Musify.Application/Users/Queries/GetUserByIdQuery.cs @@ -1,9 +1,9 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Users.Responses; namespace Musify.Application.Users.Queries { public record GetUserByIdQuery(long Id) - : IQuery >; + : IQuery >; } \ No newline at end of file diff --git a/backend/Musify.Application/Users/Queries/GetUsersQuery.cs b/backend/Musify.Application/Users/Queries/GetUsersQuery.cs index edc2e7b..a92e65c 100644 --- a/backend/Musify.Application/Users/Queries/GetUsersQuery.cs +++ b/backend/Musify.Application/Users/Queries/GetUsersQuery.cs @@ -1,4 +1,4 @@ -using Ardalis.Result; +using ErrorOr; using Mediator; using Musify.Application.Pagination; using Musify.Application.Users.Responses; @@ -6,5 +6,5 @@ using Musify.Application.Users.Responses; namespace Musify.Application.Users.Queries { public record GetUsersQuery(int PageNumber, int PageSize, string? UsernameSearch = null) - : IQuery >>; + : IQuery >>; } diff --git a/backend/Musify.StreamingGateway/Authentication/TicketValidator.cs b/backend/Musify.StreamingGateway/Authentication/TicketValidator.cs index dd0cf12..ef20e20 100644 --- a/backend/Musify.StreamingGateway/Authentication/TicketValidator.cs +++ b/backend/Musify.StreamingGateway/Authentication/TicketValidator.cs @@ -1,5 +1,5 @@ using System.Security.Cryptography; -using Ardalis.Result; +using ErrorOr; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; @@ -35,25 +35,25 @@ public sealed class TicketValidator : IDisposable }; } - public async Task> ValidateTicketAsync(string? token) + public async Task> ValidateTicketAsync(string? token) { if (string.IsNullOrWhiteSpace(token)) - return Result.Unauthorized(); + return Error.Unauthorized(); var result = await _handler.ValidateTokenAsync(token, _validationParameters); if (!result.IsValid) - return Result.Unauthorized(); + return Error.Unauthorized(); if (!result.Claims.TryGetValue("prefix", out var claim)) - return Result.Unauthorized(); + return Error.Unauthorized(); if (claim is not string prefix) - return Result.Unauthorized(); + return Error.Unauthorized(); if (string.IsNullOrEmpty(prefix)) - return Result.Unauthorized(); + return Error.Unauthorized(); - return Result.Success(prefix); + return prefix; } public void Dispose() => _rsa.Dispose(); diff --git a/backend/Musify.StreamingGateway/Middleware/TicketValidationMiddleware.cs b/backend/Musify.StreamingGateway/Middleware/TicketValidationMiddleware.cs index b282d39..3d079ad 100644 --- a/backend/Musify.StreamingGateway/Middleware/TicketValidationMiddleware.cs +++ b/backend/Musify.StreamingGateway/Middleware/TicketValidationMiddleware.cs @@ -30,7 +30,7 @@ public sealed class TicketValidationMiddleware( var validation = await ticketValidator.ValidateTicketAsync(token); - if (!validation.IsSuccess) + if (validation.IsError) { logger.LogWarning("Rejected media request {Path}: missing or invalid ticket", path); context.Response.StatusCode = StatusCodes.Status401Unauthorized; diff --git a/backend/Musify.StreamingGateway/Musify.StreamingGateway.csproj b/backend/Musify.StreamingGateway/Musify.StreamingGateway.csproj index 009b929..0041602 100644 --- a/backend/Musify.StreamingGateway/Musify.StreamingGateway.csproj +++ b/backend/Musify.StreamingGateway/Musify.StreamingGateway.csproj @@ -5,7 +5,7 @@ - + diff --git a/backend/Musify.Worker/Musify.Worker.csproj b/backend/Musify.Worker/Musify.Worker.csproj index 73fc053..7e13d15 100644 --- a/backend/Musify.Worker/Musify.Worker.csproj +++ b/backend/Musify.Worker/Musify.Worker.csproj @@ -5,7 +5,6 @@ -