8.6 KiB
MusifyBackend — Resumen de cambios (2026-05-14)
Este documento resume todos los cambios aplicados hasta ahora en la rama master durante esta iteración.
Nota: El proyecto compila en
Releaseal cierre de estos cambios.
1) Mensajería robusta: MassTransit + EF Outbox
Objetivo: hacer la publicación de eventos confiable y transaccional (DB + mensajes) y tolerar redelivery en consumidores.
Cambios principales
- Se integró MassTransit EntityFramework Outbox con PostgreSQL (
UsePostgres+UseBusOutbox). - Se añadieron entidades/tablas de Inbox/Outbox en el
DbContext. - Se generó y añadió una migración para las tablas de outbox/inbox.
- Se ajustó la configuración de endpoints para aplicar:
- Retry (exponential backoff)
- Idempotencia en consumo usando
UseEntityFrameworkOutbox<Database>()
- Se ajustó el orden de operaciones para el patrón outbox: publicar evento y luego
SaveChanges.
Archivos involucrados (principalmente)
Infrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.csInfrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Endpoints.csInfrastructure/Persistence/Database.csInfrastructure/Persistence/Migrations/20260514095113_AddMassTransitOutbox.csApplication/Abstractions/Infrastructure/IEventBus.csInfrastructure/MassTransit/EventBus/MassTransitEventBus.cs
2) Workflows: Courier RoutingSlip para imágenes y audio
Objetivo: mantener el pipeline asíncrono (descarga, resize/transcode, upload, update de entidades) con reintentos e idempotencia.
Fix importante en workflow de imágenes
- Se corrigió el nombre de actividad del paso de Upload del tamaño Medium (antes duplicaba el nombre de
ResizeMedium).
Archivos:
Infrastructure/MassTransit/RoutingSlip/Builders/PictureWorkflowRoutingSlipBuilder.csInfrastructure/MassTransit/RoutingSlip/ActivityNames.cs
Fix importante en compensación de uploads
UploadFileToBucketActivityahora registra correctamente el object key completo (ruta + filename) para que la compensación borre el objeto correcto.
Archivo:
Infrastructure/MassTransit/Activities/Files/UploadFileToBucketActivity.cs
3) Uploads (Opción B): Presigned PUT URL + Create/Update con nombres
Objetivo: separar la subida de binarios (S3) de la operación de dominio (Create/Update), evitando rollbacks complejos y haciendo el flujo más robusto.
Endpoint/Commands añadidos (request presigned URL)
- Playlist picture:
Application/PlayLists/Commands/RequestPlayListPictureUploadCommand.csApplication/PlayLists/Handlers/RequestPlayListPictureUploadCommandHandler.csApplication/PlayLists/Responses/PlayListPictureUploadResponse.cs
- Track picture + audio:
Application/Tracks/Commands/RequestTrackUploadUrlsCommand.csApplication/Tracks/Handler/RequestTrackUploadUrlsCommandHandler.csApplication/Tracks/Responses/TrackUploadUrlsResponse.cs
Storage: presigned PUT
- Se añadió soporte para generar presigned PUT URLs:
Application/Abstractions/Infrastructure/IStorageService.csInfrastructure/Services/StorageService.cs(GetUploadUrlAsync)
4) Limpieza: eliminar V1 y normalizar nombres (V2 → “normal”)
Objetivo: eliminar comandos/handlers “V1” (subida directa por stream/multipart) y dejar un único set de comandos “normales” con el contrato final.
Resultado
CreatePlayListCommand,UpdatePlayListCommandyCreateTrackCommandquedaron con el contrato nuevo (nombres/metadata, no streams).- Se eliminaron archivos
*V2*ya innecesarios.
Archivos clave:
Application/PlayLists/Commands/CreatePlayListCommand.csApplication/PlayLists/Handlers/CreatePlayListCommandHandler.csApplication/PlayLists/Commands/UpdatePlayListCommand.csApplication/PlayLists/Handlers/UpdatePlayListCommandHandler.csApplication/Tracks/Commands/CreateTrackCommand.csApplication/Tracks/Handler/CreateTrackCommandHandler.cs
5) Prefijo de seguridad: uploads/{userId}/... para originales
Objetivo: reducir superficie (y colisiones) haciendo que los objetos originales queden naturalmente “namespaced” por usuario.
Cambios
- Las keys de originales (playlist original picture, track original picture, track original audio) ahora se generan bajo:
uploads/{userId}/...
- Se añadieron overloads de rutas para construir keys con
userId. - Los handlers de request presigned URL ahora generan keys usando el prefijo con
userId. - Los eventos de workflows (sourceKey) se publican con la key prefijada.
- El borrado de playlist y track usan keys prefijadas dentro de sus workflows de delete.
Archivos:
Application/Configuration/PlayListConfiguration.csApplication/Configuration/TrackConfiguration.csApplication/PlayLists/Handlers/RequestPlayListPictureUploadCommandHandler.csApplication/Tracks/Handler/RequestTrackUploadUrlsCommandHandler.csApplication/PlayLists/Handlers/CreatePlayListCommandHandler.csApplication/PlayLists/Handlers/UpdatePlayListCommandHandler.csApplication/Tracks/Handler/CreateTrackCommandHandler.csApplication/PlayLists/Handlers/DeletePlayListCommandHandler.cs
6) Normalización de separadores en keys S3 (evitar \\ en Windows)
Objetivo: evitar que Path.Combine introduzca separadores \\ en keys S3 (lo cual es incorrecto/inesperado en S3, y rompe interoperabilidad).
Cambios
- Se reemplazaron combinaciones de keys que usaban
Path.Combinepor joins con/en puntos críticos.
Archivos:
Application/Configuration/PlayListConfiguration.csApplication/Configuration/TrackConfiguration.csInfrastructure/MassTransit/Activities/Files/UploadFileToBucketActivity.csInfrastructure/Services/StorageService.cs
7) Validaciones en Application eliminadas (delegadas a API)
Objetivo: evitar duplicar validaciones de formato (extensiones/strings) si la capa API ya se encarga.
Cambios
- Se eliminó el helper de validación creado inicialmente y los checks en handlers.
Archivos:
- Eliminado:
Application/Validation/UploadObjectNameValidator.cs - Ajustados:
Application/PlayLists/Handlers/CreatePlayListCommandHandler.csApplication/PlayLists/Handlers/UpdatePlayListCommandHandler.csApplication/Tracks/Handler/CreateTrackCommandHandler.cs
8) Documento de mitigaciones (presigned uploads)
Se añadió documentación de hardening/mitigaciones contra abuso/spam en endpoints presigned.
Archivo:
docs/presigned-upload-hardening.md
9) Notas de compatibilidad / impacto
- Este cambio rompe compatibilidad con la API anterior si existían endpoints que aceptaban multipart/streams para Create/Update (ahora se espera el flujo presigned y luego Create/Update con nombres).
- Los objetos originales ahora viven bajo
uploads/{userId}/.... Objetos antiguos fuera de ese prefijo pueden quedar huérfanos si ya existían de antes.
10) Estado final
dotnet build MusifyBackend.slnx -c Release✅
11) Deletes unificados con Workflows (RoutingSlip)
Objetivo: homogeneizar deletes de Track/PlayList usando Courier RoutingSlip con actividades granulares e idempotentes.
Cambios
- Se añadió
LifeCycleStatus(Active/Removing) aTrackyPlayListy se generó migración. - Track delete:
- Se eliminó la activity monolítica y el slip ahora encadena: marcar como removing → borrar N ficheros (condicional) → borrar en DB.
- PlayList delete:
- Se añadió
DeletePlayListEvent+ consumer + routing slip builder + activities para marcar como removing, borrar pictures (si no son preset) y borrar en DB.
- Se añadió
- Se endureció la idempotencia de borrado en S3: si una key no existe, se loguea y el paso se considera completado.
- Se eliminaron
RemoveFileEvent/RemoveFileConsumerpor quedar sin usos.
Archivos clave:
Domain/Entities/LifeCycleStatus.csDomain/Entities/Track.csDomain/Entities/PlayList.csApplication/Events/DeletePlayListEvent.csApplication/PlayLists/Handlers/DeletePlayListCommandHandler.csApplication/Tracks/Handler/DeleteTrackCommandHandler.csInfrastructure/MassTransit/Consumers/DeleteTrackConsumer.csInfrastructure/MassTransit/Consumers/DeletePlayListConsumer.csInfrastructure/MassTransit/RoutingSlip/Builders/DeleteTrackRoutingSlipBuilder.csInfrastructure/MassTransit/RoutingSlip/Builders/DeletePlayListRoutingSlipBuilder.csInfrastructure/MassTransit/Activities/Files/RemoveFileFromBucketActivity.csInfrastructure/MassTransit/DependencyInjection/MassTransitDependencyInjection.Registration.csInfrastructure/Persistence/Migrations/20260514161518_AddLifeCycleStatus.cs