veza/veza-backend-api/internal/workers/analytics_job.go

89 lines
2.6 KiB
Go

package workers
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/google/uuid"
"go.uber.org/zap"
"gorm.io/gorm"
)
// AnalyticsEventJob représente un job d'enregistrement d'événement analytics générique
type AnalyticsEventJob struct {
EventName string // Nom de l'événement (ex: "track_play", "user_login", "file_upload")
UserID *uuid.UUID // ID de l'utilisateur (nullable pour événements anonymes)
Payload map[string]interface{} // Données additionnelles de l'événement
}
// NewAnalyticsEventJob crée un nouveau job d'analytics générique
func NewAnalyticsEventJob(eventName string, userID *uuid.UUID, payload map[string]interface{}) *AnalyticsEventJob {
if payload == nil {
payload = make(map[string]interface{})
}
return &AnalyticsEventJob{
EventName: eventName,
UserID: userID,
Payload: payload,
}
}
// AnalyticsEvent représente un événement analytics en base de données
type AnalyticsEvent struct {
ID uuid.UUID `gorm:"type:uuid;primaryKey"`
EventName string `gorm:"not null;index:idx_analytics_events_name"`
UserID *uuid.UUID `gorm:"type:uuid;index:idx_analytics_events_user_id"`
Payload string `gorm:"type:jsonb"` // Stocké en JSONB pour PostgreSQL
CreatedAt time.Time `gorm:"autoCreateTime;index:idx_analytics_events_created_at"`
}
// TableName définit le nom de la table pour GORM
func (AnalyticsEvent) TableName() string {
return "analytics_events"
}
// BeforeCreate hook GORM pour générer UUID si non défini
func (a *AnalyticsEvent) BeforeCreate(tx *gorm.DB) error {
if a.ID == uuid.Nil {
a.ID = uuid.New()
}
return nil
}
// Execute exécute le job d'analytics générique
func (j *AnalyticsEventJob) Execute(ctx context.Context, db *gorm.DB, logger *zap.Logger) error {
// Valider le nom de l'événement
if j.EventName == "" {
return fmt.Errorf("event name is required")
}
// Sérialiser le payload en JSON
payloadJSON, err := json.Marshal(j.Payload)
if err != nil {
return fmt.Errorf("failed to marshal payload: %w", err)
}
// Créer l'événement analytics
event := AnalyticsEvent{
EventName: j.EventName,
UserID: j.UserID,
Payload: string(payloadJSON),
CreatedAt: time.Now(),
}
// Enregistrer en base de données
if err := db.WithContext(ctx).Create(&event).Error; err != nil {
return fmt.Errorf("failed to save analytics event: %w", err)
}
logger.Info("Analytics event recorded",
zap.String("event_name", j.EventName),
zap.String("event_id", event.ID.String()),
zap.Any("user_id", j.UserID),
zap.Int("payload_size", len(payloadJSON)),
)
return nil
}