3.7 KiB
Procesado de medios (Worker + MassTransit)
El procesado pesado (transcode de audio, miniaturas, transferencias en el bucket) ocurre fuera del request HTTP, en el Worker, orquestado con MassTransit sobre RabbitMQ.
Por qué asíncrono y con routing slips
- Transcodificar audio y redimensionar imágenes es CPU/IO intensivo: no debe bloquear una llamada a la API.
- Es un proceso multi-paso con efectos secundarios (descargar de S3 → transcodificar → subir resultados → actualizar DB). Si un paso falla, hay que deshacer los anteriores. Para eso se usan routing slips (patrón Saga de MassTransit): cada paso es una activity con su compensación.
- Outbox transaccional (EF + MassTransit): el evento se publica de forma consistente con el cambio en la DB (no se pierde ni se duplica).
Disparo
Al crear/actualizar una pista o playlist, el handler publica un evento (p. ej. CreateTrackResourcesEvent). Un consumer (CreateTrackConsumer, UpdateTrackPictureConsumer, …) construye un routing slip con la secuencia de activities y lo lanza.
Builders de routing slip
CreateTrackRoutingSlipBuilder— alta de pista (consume intents, mueve ficheros, dispara procesado).PictureWorkflowRoutingSlipBuilder— pipeline de imágenes (descargar → redimensionar → subir → actualizar).AudioWorkflowRoutingSlipBuilder— pipeline de audio (descargar → transcodificar a.m4a→ subir carpeta → actualizar).DeleteTrackRoutingSlipBuilder,DeletePlayListRoutingSlipBuilder,PlayListPictureSourceRoutingSlipBuilder.
Activities (pasos)
Agrupadas por área:
- Files:
DownloadFileFromBucketActivity,UploadFileToBucketActivity,TransferFilesToBucketActivity,CopyFileInBucketActivity,RemoveFileFromBucketActivity. - Audio:
GenerateAudioWorkflowPathsActivity,TranscodeAudioActivity(ffmpeg →.m4a),UpdateTrackAudioActivity(guardaAudioFolderNamey marcaCompleted). - Pictures:
GeneratePictureWorkflowPathsActivity,ResizePictureActivity(ImageSharp),UpdateTrackPictureActivity,UpdatePlayListPictureActivity. - Tracks/PlayLists:
MarkTrackAsRemovingActivity,DeleteTrackFromDbActivity,PublishTrackProcessingEventsActivity, y equivalentes de playlist. - UploadIntents:
ConsumeUploadIntentsActivity.
RoutingSlipCleanUpConsumer reacciona a Completed/Faulted para limpiar (p. ej. borrar el directorio temporal de trabajo).
Transcode de audio
AudioTranscoderService invoca ffmpeg leyendo el original por stdin y produciendo en un directorio de trabajo un único audio.m4a: AAC con codec/bitrate/sample-rate/profile configurables y -movflags +faststart (moov al inicio → seek por range). Luego TransferFilesToBucketActivity sube esa carpeta a Tracks/ProcessedAudios/{folder}/ y UpdateTrackAudioActivity guarda el AudioFolderName (la carpeta de destino en S3, no la local) y pone el estado en Completed.
Configuración que necesita el Worker
El Worker registra: storage (S3), transcoder (ffmpeg), pictures, DB, los consumers de MassTransit y los jobs de upload intents. Su AppSettings debe tener las secciones correctas: Bucket (= webapi-storage, el mismo que la API), PlayList, Track, MassTransit, AudioTranscoder, UploadIntent, Workers (directorio temporal), InfrastructureStorage, Database.
Jobs de fondo
UploadIntentExpirationJob— marca intents caducados como expirados (libera cuota) cadaExpirationJobIntervalSeconds.TemporalUploadsCleanUpJob— limpia subidas temporales antiguas.
Corren en el host del Worker (AddUploadIntentJobs). Si no se registran en ningún proceso, los intents colgados no se limpian solos.