veza/fixtures/docs/ARCHITECTURE.md
2025-12-03 22:56:50 +01:00

14 KiB

🏗️ Architecture du Système de Fixtures Veza

Vue d'Ensemble

Le système de fixtures Veza est conçu selon une architecture modulaire et extensible qui sépare clairement les responsabilités entre la génération de données, la gestion des relations, l'intégration avec les services, et l'exécution de scénarios de test.

🎯 Principes de Conception

1. Séparation des Responsabilités

  • Core : Génération et validation des données
  • Services : Intégration spécifique à chaque service
  • Scenarios : Orchestration de tests complexes
  • Tools : Interfaces utilisateur (CLI, scripts)

2. Cohérence des Données

  • Relations bidirectionnelles automatiques
  • Validation en temps réel
  • Contraintes d'intégrité référentielle

3. Scalabilité

  • Génération parallélisable
  • Gestion mémoire optimisée
  • Support multi-environnements

4. Reproductibilité

  • Seeds déterministes
  • Configuration versionnée
  • Exports standardisés

🏛️ Architecture Détaillée

graph TB
    subgraph "Configuration Layer"
        CONFIG[Configuration Manager]
        ENV[Environment Configs]
        SEED[Seed Management]
    end
    
    subgraph "Core Layer"
        GEN[Data Generators]
        SCHEMA[Schema Validation]
        FAKER[Enhanced Faker]
        REL[Relation Manager]
    end
    
    subgraph "Service Integration Layer"
        WEB[Web Fixtures]
        CHAT[Chat Server Fixtures]
        STREAM[Stream Server Fixtures]
        API[Backend API Fixtures]
    end
    
    subgraph "Scenario Layer"
        JOURNEY[User Journey]
        PERF[Performance Tests]
        INTEG[Integration Tests]
        EDGE[Edge Cases]
    end
    
    subgraph "Interface Layer"
        CLI[CLI Tools]
        PROG[Programmatic API]
        CI[CI/CD Integration]
    end
    
    CONFIG --> GEN
    ENV --> CONFIG
    SEED --> FAKER
    
    GEN --> SCHEMA
    GEN --> REL
    FAKER --> GEN
    
    REL --> WEB
    REL --> CHAT
    REL --> STREAM
    REL --> API
    
    WEB --> JOURNEY
    CHAT --> PERF
    STREAM --> INTEG
    API --> EDGE
    
    CLI --> CONFIG
    PROG --> REL
    CI --> CLI

📦 Modules Principaux

Core Module

Configuration Manager

// Gestion centralisée de la configuration
export class ConfigurationManager {
  loadConfig(environment: string): FixtureConfig
  validateConfig(config: FixtureConfig): ValidationResult
  mergeConfigs(base: FixtureConfig, override: Partial<FixtureConfig>): FixtureConfig
}

Responsabilités:

  • Chargement des configurations d'environnement
  • Validation des paramètres
  • Fusion des configurations
  • Gestion des variables d'environnement

Data Generators

// Générateurs spécialisés par type d'entité
export abstract class BaseGenerator<T> {
  abstract generate(options?: GenerationOptions): T
  generateBatch(count: number, options?: GenerationOptions): T[]
  clearCache(): void
}

export class UserGenerator extends BaseGenerator<User> {
  // Implémentation spécifique aux utilisateurs
}

Responsabilités:

  • Génération d'entités typées
  • Gestion du cache en mémoire
  • Options de personnalisation
  • Validation des données générées

Relation Manager

// Gestionnaire central des relations entre entités
export class DataRelationManager {
  static registerEntity<T>(entity: T, type: EntityType): void
  static validateRelations(): ValidationResult
  static exportForDatabase(): DatabaseExport
  static exportForAPI(): APIExport
}

Responsabilités:

  • Enregistrement des entités
  • Maintien des relations bidirectionnelles
  • Validation de l'intégrité référentielle
  • Export dans différents formats

Service Integration Layer

Web Fixtures

export class WebFixtures {
  // MSW handlers pour mocks API
  static getMSWHandlers(): RequestHandler[]
  
  // Données localStorage
  static seedLocalStorage(): void
  
  // État d'authentification
  static setupAuthState(user: User): void
}

Responsabilités:

  • Configuration MSW (Mock Service Worker)
  • Gestion de l'état du navigateur
  • Simulation d'authentification
  • Données de session

Chat Server Fixtures

export class ChatServerFixtures {
  // Seeding base de données PostgreSQL
  static async seedDatabase(): Promise<void>
  
  // Cache Redis
  static async seedRedis(): Promise<void>
  
  // Événements WebSocket
  static generateWebSocketEvents(): WebSocketEvent[]
}

Responsabilités:

  • Population de la base de données
  • Gestion du cache Redis
  • Simulation d'événements temps réel
  • Métriques de performance

Stream Server Fixtures

export class StreamServerFixtures {
  // Sessions de streaming
  static generateStreamingSession(userId: string, trackId: string): StreamingSession
  
  // Queue de traitement audio
  static generateAudioProcessingJobs(tracks: Audio[]): ProcessingJob[]
  
  // Analytics de streaming
  static generateStreamingAnalytics(): StreamingAnalytics
}

Responsabilités:

  • Simulation de sessions de streaming
  • Queue de traitement audio
  • Métriques en temps réel
  • Données d'analytics

Scenario Layer

Scenario Framework

export abstract class BaseScenario<T> {
  abstract setup(): Promise<T>
  abstract validate(context: T): ValidationResult
  abstract cleanup(context: T): Promise<void>
}

export class UserJourneyScenario extends BaseScenario<UserJourneyContext> {
  // Implémentation spécifique au parcours utilisateur
}

Responsabilités:

  • Orchestration de tests complexes
  • Validation des résultats
  • Nettoyage après exécution
  • Métriques de performance

🔄 Flux de Données

1. Génération de Données

sequenceDiagram
    participant CLI
    participant Config
    participant Generator
    participant RelationManager
    participant Validator
    
    CLI->>Config: loadConfig(environment)
    Config->>Generator: initialize(config)
    Generator->>Generator: generateUsers()
    Generator->>RelationManager: registerUsers(users)
    Generator->>Generator: generateAudio()
    Generator->>RelationManager: registerAudio(tracks)
    RelationManager->>Validator: validateRelations()
    Validator->>CLI: ValidationResult

2. Seeding de Services

sequenceDiagram
    participant CLI
    participant RelationManager
    participant WebFixtures
    participant ChatFixtures
    participant StreamFixtures
    
    CLI->>RelationManager: getDataset()
    RelationManager->>WebFixtures: initialize(dataset)
    WebFixtures->>WebFixtures: setupMSWHandlers()
    RelationManager->>ChatFixtures: seedDatabase(dataset)
    ChatFixtures->>ChatFixtures: seedRedis(dataset)
    RelationManager->>StreamFixtures: seedStreaming(dataset)
    StreamFixtures->>CLI: success

3. Exécution de Scénarios

sequenceDiagram
    participant CLI
    participant Scenario
    participant Services
    participant Validator
    
    CLI->>Scenario: setup()
    Scenario->>Services: initializeServices()
    Services->>Scenario: ready
    Scenario->>Scenario: executeSteps()
    Scenario->>Validator: validateResults()
    Validator->>CLI: ScenarioResult

🔧 Patterns de Conception

1. Factory Pattern

export class FixtureFactory {
  static createUser(type: UserType): User {
    switch (type) {
      case 'admin': return UserGenerator.generateAdmin()
      case 'artist': return UserGenerator.generateArtist()
      default: return UserGenerator.generate()
    }
  }
}

2. Observer Pattern

export class GenerationObserver {
  onUserGenerated(user: User): void
  onAudioGenerated(audio: Audio): void
  onRelationEstablished(from: string, to: string, type: string): void
}

3. Strategy Pattern

export interface ExportStrategy {
  export(data: any): Promise<void>
}

export class JSONExportStrategy implements ExportStrategy {
  async export(data: any): Promise<void> {
    // Implémentation JSON
  }
}

export class SQLExportStrategy implements ExportStrategy {
  async export(data: any): Promise<void> {
    // Implémentation SQL
  }
}

4. Builder Pattern

export class ScenarioBuilder {
  private scenario: Partial<Scenario> = {}
  
  withUsers(count: number): this {
    this.scenario.userCount = count
    return this
  }
  
  withDuration(seconds: number): this {
    this.scenario.duration = seconds
    return this
  }
  
  build(): Scenario {
    return new Scenario(this.scenario)
  }
}

🗄️ Gestion des Données

Structure en Mémoire

interface DataStore {
  users: Map<string, User>
  audio: Map<string, Audio>
  playlists: Map<string, Playlist>
  conversations: Map<string, Conversation>
  messages: Map<string, Message>
  
  // Index pour les relations
  userTracks: Map<string, string[]>
  userPlaylists: Map<string, string[]>
  conversationParticipants: Map<string, string[]>
}

Optimisations Mémoire

  1. Lazy Loading : Chargement à la demande des relations
  2. Weak References : Éviter les fuites mémoire
  3. Pagination : Traitement par chunks pour gros datasets
  4. Cache LRU : Éviction automatique des données anciennes

Persistence

interface PersistenceAdapter {
  save(key: string, data: any): Promise<void>
  load(key: string): Promise<any>
  delete(key: string): Promise<void>
  clear(): Promise<void>
}

export class FilePersistenceAdapter implements PersistenceAdapter {
  // Implémentation fichier
}

export class DatabasePersistenceAdapter implements PersistenceAdapter {
  // Implémentation base de données
}

🔒 Sécurité et Validation

Validation des Schémas

// Utilisation de Zod pour la validation
export const UserSchema = z.object({
  id: z.string().uuid(),
  username: z.string().min(3).max(50),
  email: z.string().email(),
  // ... autres champs
})

export const validateUser = (data: unknown): User => {
  return UserSchema.parse(data)
}

Sanitisation des Données

export class DataSanitizer {
  static sanitizeUser(user: User): User {
    return {
      ...user,
      email: this.sanitizeEmail(user.email),
      username: this.sanitizeUsername(user.username)
    }
  }
  
  private static sanitizeEmail(email: string): string {
    // Nettoyage et validation
  }
}

Gestion des Secrets

export class SecretManager {
  static generateJWT(user: User): string
  static hashPassword(password: string): string
  static generateAPIKey(): string
}

🚀 Performance et Scalabilité

Génération Parallèle

export class ParallelGenerator {
  static async generateBatch<T>(
    generator: () => T,
    count: number,
    concurrency: number = 10
  ): Promise<T[]> {
    const chunks = this.createChunks(count, concurrency)
    const promises = chunks.map(chunk => 
      Promise.all(chunk.map(() => generator()))
    )
    
    const results = await Promise.all(promises)
    return results.flat()
  }
}

Optimisations Base de Données

export class BatchInserter {
  static async insertUsers(users: User[]): Promise<void> {
    const BATCH_SIZE = 1000
    const batches = this.createBatches(users, BATCH_SIZE)
    
    for (const batch of batches) {
      await this.insertBatch(batch)
    }
  }
}

Monitoring des Performances

export class PerformanceMonitor {
  static time<T>(name: string, fn: () => T): T {
    const start = Date.now()
    const result = fn()
    const duration = Date.now() - start
    
    this.recordMetric(name, duration)
    return result
  }
  
  static recordMetric(name: string, value: number): void {
    // Enregistrement des métriques
  }
}

🧪 Tests et Qualité

Architecture de Tests

test/
├── unit/                    # Tests unitaires
│   ├── generators/         # Tests des générateurs
│   ├── utils/             # Tests des utilitaires
│   └── services/          # Tests des services
├── integration/           # Tests d'intégration
│   ├── cross-service/     # Tests inter-services
│   └── scenarios/         # Tests de scénarios
└── performance/          # Tests de performance
    ├── load/             # Tests de charge
    └── stress/           # Tests de stress

Stratégies de Test

  1. Unit Tests : Chaque générateur et utilitaire
  2. Integration Tests : Communication entre modules
  3. Performance Tests : Métriques et benchmarks
  4. End-to-End Tests : Scénarios complets

🔄 CI/CD Integration

Pipeline de Validation

# Validation automatique des fixtures
- name: Validate Fixtures
  run: |
    npm run generate -- --dry-run
    npm run validate -- --check-relations
    npm run test -- --coverage    

Déploiement Automatique

# Déploiement des fixtures en staging
- name: Deploy Fixtures
  run: |
    npm run seed -- --env staging --service all
    npm run validate -- --env staging    

🔮 Extensibilité

Ajout de Nouveaux Générateurs

// 1. Créer le générateur
export class MyEntityGenerator extends BaseGenerator<MyEntity> {
  generate(options?: MyEntityOptions): MyEntity {
    // Implémentation
  }
}

// 2. Enregistrer dans le système
DataRelationManager.registerGenerator('myEntity', MyEntityGenerator)

// 3. Ajouter au CLI
CLI.addCommand('generate-my-entity', MyEntityGenerator.generate)

Nouveaux Types d'Export

// 1. Implémenter l'interface
export class XMLExportStrategy implements ExportStrategy {
  async export(data: any): Promise<void> {
    // Conversion en XML
  }
}

// 2. Enregistrer la stratégie
ExportManager.registerStrategy('xml', XMLExportStrategy)

Intégration de Nouveaux Services

// 1. Créer la classe de fixtures
export class MyServiceFixtures {
  static async initialize(): Promise<void>
  static async seed(data: any): Promise<void>
  static async validate(): Promise<ValidationResult>
}

// 2. Enregistrer dans le système
ServiceRegistry.register('my-service', MyServiceFixtures)

Cette architecture modulaire et extensible permet au système de fixtures Veza de s'adapter aux besoins évolutifs de la plateforme tout en maintenant la cohérence, la performance et la qualité des données générées.