Aller au contenu
FR EN
Contact
Tous les articles

Laravel + VueJS : une stack éprouvée pour les concours

Dev 6 min

Une plateforme de concours a un profil de charge très particulier : calme pendant des semaines, puis une vague de candidats dans les derniers jours avant la clôture, souvent depuis des connexions mobiles instables. C’est précisément à ce moment que la moindre faiblesse se paie : un dossier enregistré deux fois, un paiement non rattaché, un serveur qui ne répond plus à la veille de la date limite. Cet article explique comment une stack Laravel (API) et VueJS (interface) répond à ces contraintes, en s’appuyant sur la documentation officielle de Laravel 12.

Objectifs d’apprentissage

  • comprendre pourquoi une requête web doit rester courte, et comment les files d’attente (queues) le permettent ;
  • savoir limiter le débit d’une route sensible avec le limiteur de Laravel ;
  • garantir l’idempotence d’une inscription, c’est-à-dire qu’un double envoi ne crée pas deux dossiers ;
  • préparer un pic de charge par un test de charge et une supervision.

1. Le modèle mental : une requête doit être courte

Un serveur web traite les requêtes avec un nombre limité de processus. Si chacun reste occupé plusieurs secondes (générer un PDF de convocation, envoyer un courriel, appeler l’API d’un opérateur de paiement), la file des requêtes en attente s’allonge et le site paraît « tomber », alors que la machine n’est pas saturée en calcul. La règle est donc : la requête enregistre l’essentiel et répond ; le reste est différé.

La documentation de Laravel le formule ainsi : les files d’attente permettent de déplacer les tâches longues en arrière-plan pour que l’application réponde aux requêtes web avec une grande rapidité.

2. Les files d’attente en pratique

Un job est une classe qui décrit une tâche différée. À l’inscription, on enregistre le dossier en base, puis on dispatche la génération du récépissé et l’envoi du courriel :

// Contrôleur : on répond vite.
$candidature = Candidature::create($donneesValidees);
GenererRecepisse::dispatch($candidature);

return response()->json(['numero' => $candidature->numero], 201);

Côté serveur, des processus workers consomment la file. Avec le pilote Redis, plus performant que la base de données pour ce rôle, on les fait tourner sous Supervisor, qui les relance en cas d’arrêt. La documentation propose une configuration de ce type :

[program:laravel-worker]
command=php /var/www/concours/artisan queue:work --sleep=3 --tries=3 --max-time=3600
numprocs=8
autostart=true
autorestart=true
stopwaitsecs=3600

Trois réglages méritent d’être compris :

  • --tries=3 : un job qui échoue est retenté, puis rangé dans la table failed_jobs où on peut l’examiner et le relancer ;
  • backoff : le délai entre deux tentatives, qui peut croître (par exemple [1, 5, 10] secondes) pour ne pas harceler un service tiers déjà en difficulté ;
  • numprocs : le nombre de workers en parallèle, à dimensionner selon le serveur. Laravel Horizon permet de piloter ces paramètres et de suivre les files depuis un tableau de bord.

3. Limiter le débit des routes sensibles

Un formulaire d’inscription public attire aussi les robots. Laravel fournit un limiteur de débit déclaré dans AppServiceProvider :

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

public function boot(): void
{
    RateLimiter::for('inscription', function (Request $request) {
        return Limit::perMinute(10)->by($request->ip());
    });
}

On l’attache à la route avec le middleware throttle:inscription. Au-delà du seuil, Laravel répond par le code HTTP 429 (Too Many Requests), que l’interface doit traduire par un message clair plutôt que par une erreur générique. Côté jobs, le middleware RateLimited joue le même rôle vis-à-vis d’un service externe : un job qui dépasse la limite est remis dans la file avec un délai.

4. L’idempotence : un double clic ne doit pas créer deux dossiers

C’est la propriété la plus importante et la plus souvent négligée. Un candidat dont la connexion hésite clique deux fois ; le navigateur renvoie le formulaire ; l’opérateur de paiement rappelle votre webhook. Chaque fois, le résultat doit être le même qu’avec un seul envoi. On combine trois niveaux :

  1. La base de données, dernier rempart : une contrainte d’unicité (par exemple sur le couple numéro de pièce d’identité et session de concours) rend physiquement impossible le doublon.
  2. Le code : une transaction englobe la création du dossier et de ses pièces, pour qu’une erreur au milieu ne laisse pas de dossier à moitié créé.
  3. Les jobs : l’interface ShouldBeUnique garantit qu’un même job (par exemple le rapprochement d’un paiement) n’est présent qu’une fois dans la file ; le middleware WithoutOverlapping empêche deux exécutions simultanées sur la même clé.

Retenez la hiérarchie : l’interface réduit les doublons, le code les évite, la base de données les interdit.

5. Le rôle de VueJS : une interface qui protège le serveur

Une application monopage en VueJS ne se contente pas d’être agréable. Bien conçue, elle allège la charge et améliore la qualité des données :

  • validation immédiate des champs (format du numéro de téléphone, taille des pièces jointes) avant tout envoi, la validation serveur restant obligatoire ;
  • bouton désactivé pendant l’envoi, première défense contre le double clic ;
  • sauvegarde du brouillon dans le navigateur, pour qu’une coupure réseau ne fasse pas perdre vingt minutes de saisie ;
  • gestion explicite des erreurs 422 (validation) et 429 (trop de requêtes), avec un message qui dit quoi faire.

6. Préparer le pic plutôt que le subir

Deux pratiques distinguent une plateforme qui tient d’une plateforme qui espère tenir :

  • Le test de charge, avant l’ouverture : un outil comme k6 simule des centaines d’utilisateurs simultanés sur le parcours d’inscription et révèle le premier goulot d’étranglement, souvent une requête SQL sans index.
  • La supervision pendant la campagne : taille des files, nombre de jobs en échec, temps de réponse, espace disque. Un tableau de bord consulté chaque matin vaut mieux qu’une alerte reçue trop tard.

Enfin, mettez en cache les données de référence qui ne changent pas pendant la campagne (liste des filières, centres d’examen) avec Cache::remember : ce sont souvent les requêtes les plus fréquentes.

Erreurs fréquentes

  • Envoyer les courriels pendant la requête d’inscription.
  • Compter sur le seul bouton désactivé pour éviter les doublons.
  • Découvrir le comportement de la plateforme sous charge le jour de la clôture.
  • Oublier de surveiller la table des jobs en échec : un récépissé jamais envoyé est un candidat inquiet au téléphone.

À retenir

Courte requête, travail différé, débit limité, idempotence garantie par la base, charge testée à l’avance : ce sont ces cinq principes, plus que le choix du framework, qui font tenir une plateforme de concours.

Références

Votre retour d'expérience nous intéresse

Avez-vous fait d'autres choix ? Rencontré d'autres difficultés ? Partagez votre expérience ou vos questions en commentaire : nous lisons et répondons à chaque message.

Laisser un commentaire

Besoin d'une application métier sur mesure ?

Plateforme de concours, gestion des personnels, assistant IA, e-learning : nous concevons, déployons et maintenons des applications adaptées à votre structure.

Parlons de votre projet

Commentaires

Aucun commentaire pour le moment : soyez le premier à partager votre expérience.

Laisser un commentaire

Votre premier commentaire est relu avant publication. Merci de rester courtois et constructif.

Un email par semaine, zéro bruit

Nos regards sur le Dev, la Data Science et l'IA, tirés de nos projets. Désabonnement en un clic.

Vos données ne sont ni revendues ni partagées. Politique de confidentialité