Phase 1 - Backend tests: - Add PlaybackAnalytics to AutoMigrate in setupTestTrackHandler - Create migration 081_create_playback_analytics.sql for production - PlaybackAnalyticsService: return ErrTrackNotFound for missing track - RecordPlay handler: return 404 when track not found - CreateShare: use RespondSuccess, fix services.ErrTrackNotFound/ErrForbidden - GetTrackLikes, UnlikeTrack: use RespondSuccess for consistent response - GetUserLikedTracks test: fix route /users/:id/likes and params - GetSharedTrack_InvalidToken: set share service in test Phase 4 - Job queue transcoding: - Add EnqueueTranscodingJob to JobEnqueuer interface - Add TypeTranscoding and processTranscodingJob (stub) in JobWorker - MockJobEnqueuer: implement EnqueueTranscodingJob Phase 5 - Gamification cleanup: - Move api_manager.go to internal/api/archive/ - Add archive/README.md documenting archived modules - Update TODOS_AUDIT.md and FEATURE_STATUS.md
102 lines
3.1 KiB
Go
102 lines
3.1 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/google/uuid"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// JobEnqueuer interface pour éviter le cycle d'importation
|
|
// BE-SVC-003: Implement background job queue
|
|
type JobEnqueuer interface {
|
|
EnqueueEmailJob(to, subject, body string)
|
|
EnqueueEmailJobWithTemplate(to, subject, templateName string, templateData map[string]interface{})
|
|
EnqueueThumbnailJob(inputPath, outputPath string, width, height int)
|
|
EnqueueAnalyticsJob(eventName string, userID *uuid.UUID, payload map[string]interface{})
|
|
EnqueueTranscodingJob(trackID uuid.UUID, inputPath, outputDir string)
|
|
}
|
|
|
|
// JobService gère les jobs en arrière-plan
|
|
// BE-SVC-003: Implement background job queue
|
|
type JobService struct {
|
|
logger *zap.Logger
|
|
jobEnqueuer JobEnqueuer
|
|
}
|
|
|
|
// Job types
|
|
const (
|
|
TypeEmailSend = "email:send"
|
|
TypeThumbnailGenerate = "thumbnail:generate"
|
|
TypeAnalyticsProcess = "analytics:process"
|
|
TypeWebhookDelivery = "webhook:delivery"
|
|
TypeTranscoding = "transcoding"
|
|
)
|
|
|
|
// EmailPayload représente les données pour l'envoi d'email
|
|
type EmailPayload struct {
|
|
To string
|
|
Subject string
|
|
Body string
|
|
}
|
|
|
|
// ThumbnailPayload représente les données pour la génération de miniatures
|
|
type ThumbnailPayload struct {
|
|
TrackID uint
|
|
FileID string
|
|
FilePath string
|
|
}
|
|
|
|
// NewJobService crée un nouveau service de jobs
|
|
func NewJobService(logger *zap.Logger) *JobService {
|
|
return &JobService{
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// SetJobEnqueuer définit le JobEnqueuer pour le service
|
|
// BE-SVC-003: Connect JobService to JobWorker
|
|
func (s *JobService) SetJobEnqueuer(jobEnqueuer JobEnqueuer) {
|
|
s.jobEnqueuer = jobEnqueuer
|
|
}
|
|
|
|
// EnqueueEmail enfile un job d'envoi d'email
|
|
// BE-SVC-003: Implement background job queue for email sending
|
|
func (s *JobService) EnqueueEmail(ctx context.Context, payload *EmailPayload) error {
|
|
if s.jobEnqueuer == nil {
|
|
s.logger.Warn("JobEnqueuer not set, email job not enqueued",
|
|
zap.String("to", payload.To),
|
|
zap.String("subject", payload.Subject))
|
|
return nil // Fail gracefully
|
|
}
|
|
|
|
s.logger.Info("Email job enqueued",
|
|
zap.String("to", payload.To),
|
|
zap.String("subject", payload.Subject))
|
|
|
|
// Enqueue via JobEnqueuer (JobWorker)
|
|
s.jobEnqueuer.EnqueueEmailJob(payload.To, payload.Subject, payload.Body)
|
|
return nil
|
|
}
|
|
|
|
// EnqueueThumbnail enfile un job de génération de miniature
|
|
// BE-SVC-003: Implement background job queue for thumbnail generation
|
|
func (s *JobService) EnqueueThumbnail(ctx context.Context, payload *ThumbnailPayload) error {
|
|
if s.jobEnqueuer == nil {
|
|
s.logger.Warn("JobEnqueuer not set, thumbnail job not enqueued",
|
|
zap.Uint("track_id", payload.TrackID))
|
|
return nil // Fail gracefully
|
|
}
|
|
|
|
s.logger.Info("Thumbnail job enqueued",
|
|
zap.Uint("track_id", payload.TrackID))
|
|
|
|
// Enqueue via JobEnqueuer (assuming default dimensions)
|
|
// Note: ThumbnailPayload uses uint for TrackID, but we need file paths
|
|
// This is a simplified version - actual implementation may need adjustment
|
|
if payload.FilePath != "" {
|
|
// Default thumbnail size
|
|
s.jobEnqueuer.EnqueueThumbnailJob(payload.FilePath, payload.FilePath+".thumb", 300, 300)
|
|
}
|
|
return nil
|
|
}
|