PrestaConcept
Nos réalisations
Nos métiers
  • Découvrez nos métiers
  • Développement web sur mesure

    Nous développons en méthode agile des back sous le framework PHP Symfony, des front en Angular.

  • Maintenance d'applications

    Maintien en condition opérationnelle de votre plateforme Symfony.

  • Expertise Symfony

    Coaching, formation, audit et conseil.

  • Hébergement et Infogérance

    Une expertise de l'hébergement depuis plus de 15 ans et l’infogérance de centaines de machines en production actuellement.

  • Qui sommes nous
  • Découvrez Prestaconcept
  • PrestaConcept

    Notre histoire, nos convictions, notre vision... Découvrez ce qui nous anime !

  • L'équipe

    Plus de 15 ans minimum d'expérience sur Symfony.

  • Nos engagements RSE

    Une société engagée pour un numérique responsable.

  • Nos convictions

    Co-construction, transparence.. Les principes qui guident nos collaborations !

  • Nous rejoindre

    Envie de nous rejoindre ? Consultez nos offres !

  • Blog
    J'ai un projet Nous contacter
    J'ai un projet Nous contacter Menu
    • Accueil
    • Blog
    • Tech
    • Scheduler, Webhook et RemoteEvent : des composants prometteurs attendus pour Symfony 6.3

    Blog

    Scheduler, Webhook et RemoteEvent : des composants prometteurs attendus pour Symfony 6.3

    David Gaussinel
    David Gaussinel Directeur des opérations
    Publié le jeudi 6 avril 2023

    La version 6.3 de Symfony qui sortira en mai prochain va apporter son lot d’améliorations et de nouvelles possibilités sur des composants existants comme chaque nouvelle version de Symfony. Elle apportera également de nouveaux composants qui vont repousser encore plus loin les capacités que nous offre Symfony.

    C'est encore lors des keynotes de conférences Symfony que ces composants ont été annoncés. Les plus attentifs auront eu l'info avant en suivant l'activité du Github de Symfony. Et pour ceux qui ont donc loupé jusqu'à aujourd'hui l'existence de ces composants encore expérimentaux et disponibles dans la future version 6.3, je vous en propose donc une petite présentation.

    C’est quoi un Webhook ?

    Moins connu que les API Rest, GraphQL ou même ce bon vieux SOAP, mais allant souvent de pair avec, voire inclue dans la documentation de l’API elle-même, les webhooks sont pourtant très répandus, et même très anciens sans qu’il s’agisse pour autant d’une technologie définie formellement.

    Une application peut consommer une API pour récupérer de la data ou avoir une action. Mais si l'application a besoin par exemple d'être informée d'une mise à jour du système tiers, et que seul l’API soit disponible, on aura alors besoin de venir périodiquement consommer l’API pour vérifier si l’information est mise à jour, ce qui peut être peu performant voire peu pratique si on a besoin d’être mis au courant rapidement du changement d’une information. Du coup, il est souvent possible sur le système tiers de définir un webhook en paramétrant une URL de callback de votre application qui sera appelée lorsque nécessaire par le système tiers. La communication se fait bien alors du coup à l’initiative du système tiers dès que c’est nécessaire.

    En résumé imaginez que vous vouliez que votre application soit informée, à chaque fois qu'un événement précis se passe dans un système extérieur, vous allez alors configurer une URL de callback sur le système en question, qui fera lui-même l'appel http sur votre application.

    On l’a dit, les webhooks ce n’est pas normalisé, la communication peut être sécurisée de différentes façons, voire pas du tout, le contenu de la requête peut être du json, c’est souvent le cas, mais pourrait être n’importe quoi. C'est ce qui rend parfois si compliqué l'utilisation de ces webhooks c'est qu'il faut s'adapter à ce que le système extérieur au votre a défini.

    Le composant Webhook

    Annoncé par Fabien Potencier au dernier SymfonyCon 2022 à Paris, et mergé dans la branche 6.3 en décembre dernier, il est donc possible de tester dès à présent les composants Webhook et RemoteEvent qui vont souvent aller de pair.

    Jusque-là en Symfony pour pouvoir gérer un webhook, vous deviez tout prendre à votre charge, la réception de la requête dans un controller, son routage donc, son traitement, la vérification de l’appel, etc. Le composant Webhook va permettre d’uniformiser le traitement des webhooks en définissant déjà un seul point de routage unique, par exemple ici /webhook et qui directement sera géré par le composant.

    webhook:
           resource: @FrameworkBundle/Resources/config/routing/webhook.xml'
           prefix: /webhook
    

    La configuration du composant permettra de déclarer les services pris en charge et une clé va définir l’url à communiquer pour le callback, par exemple ici l’url sera du coup /webhook/mailgun.

    framework:
        webhook:
            routing:
                mailgun:
                    service: mailer.webhook.request_parser.mailgun
    

    Un cas classique d’API qui envoie des mises à jour de statut via des webhooks sont les systèmes d’envoi de mail ou SMS comme Mailjet ou ici dans l’exemple Mailgun. Ces systèmes sont déjà très bien intégrés dans l’écosystème Symfony grâce au composant Notifier et de nombreux bridges existants. C’est donc tout naturellement que ces bridges vont être enrichis pour pouvoir non seulement envoyer des mails par exemple mais aussi obtenir des statuts en retour, par exemple est-ce que le mail a bien été envoyé.

    Dans notre exemple, le bridge mailgun-mailer s’est donc vu ajouter dans sa future version 6.3 un service mailer.webhook.request_parser.mailgun pour pouvoir parser le webhook reçu.

    Évidemment, rien ne vous empêchera d’écrire vos propres parsers pour des webhooks non encore prévus, que ce soit pour des services d’envoi de mail ou de SMS mais aussi d’autres ! Un terrain de jeu idéal d’ailleurs serait de pouvoir traiter plus facilement les webhooks des systèmes de paiement par exemple.

    Le composant RemoteEvent

    Une fois le webhook reçu et parsé, faut-il encore pouvoir réagir dans votre application en fonction de son contenu. Si par exemple, nous reprenons notre exemple de mailgun, nous allons peut-être vouloir marquer des mails comme envoyés ou incrémenter un compteur pour gérer des statistiques par exemple.

    L’idée ici est de pouvoir transformer les données reçues sur le webhook en un RemoteEvent qui devra être consommé par votre application pour être traité. Le RemoteEvent va être généré par un PayloadConverter.

    Dans notre cas de Postgun, un MailgunPayloadConverter est bien présent dans le code et sera appelé par le parser pour générer un RemoteEvent. Mais pour standardiser un peu les choses, le composant RemoteEvent prévoit déjà des abstractions pour des événements liés aux mails et aux SMS. Il permet par exemple d’avoir un événement MailerDeliveryEvent qui peut être déclenché quand le système d’envoi de mail retourne une information sur l’état d’envoi du mail, ce qui est très souvent le cas.

    namespace Symfony\Component\RemoteEvent\Event\Mailer;
    
    /**
     * @author Fabien Potencier <fabien@symfony.com>
     *
     * @experimental in 6.3
     */
    final class MailerDeliveryEvent extends AbstractMailerEvent
    {
        public const RECEIVED = 'received';
        public const DROPPED = 'dropped';
        public const DELIVERED = 'delivered';
        public const DEFERRED = 'deferred';
        public const BOUNCE = 'bounce';
    
        private string $reason = '';
    
        public function setReason(string $reason): void
        {
            $this->reason = $reason;
        }
    
        public function getReason(): string
        {
            return $this->reason;
        }
    }
    

    Le fait de standardiser ainsi l’événement que les bridges retourneront lors du changement de statut d’un mail fait en sorte que le code que vous allez écrire pour consommer cet événement puisse être complètement agnostique du service d’envoi de mail et rester le même en cas de changement de l'envoi du mail.

    Dans notre cas ici, le seul travail que vous aurez du coup à faire pour réellement traiter le Webhook reçu sera donc de consommer le RemoteEvent en écrivant un consumer ainsi.

    use Symfony\Component\RemoteEvent\Attribute\AsRemoteEvent Consumer;
    use Symfony\Component\RemoteEvent\Event Mailer\MailerDeliveryEvent;
    
    #AsRemoteEvent Consumer(name: 'postgun')]
    class MailSentConsumer
    {
        public function consume(MailerDeliveryEvent $event): void {
            # Ici votre code peut traiter les données de l'$event
        }
    }
    

    L’attribut AsRemoteEventConsumer permet de déclarer sa classe comme devant consommer des RemoteEvent et recevra donc sur sa fonction consume() un MailerDeliveryEvent. Vous pourrez alors réagir en fonction du contenu de cet événement.

    Le composant Scheduler

    Réinventer la crontab et pouvoir enfin se passer de devoir programmer en dehors de votre application ces tâches récurrentes, beaucoup de projets ont essayé mais sans grand succès pour le moment. Souvent trop complexes dans leur mise en œuvre ou trop imprécis, pas assez généralisés aussi sans doute, on finit toujours par se dire qu’une bonne crontab c’est mieux. Mais force est de constater que ça comporte aussi des désavantages : les logs sont gérés à part, difficilement administrables depuis l’application, la définition même de la crontab se fait en dehors du projet…

    C’est lors du SymfonyLive Paris 2023, très récemment donc, qu’un Fabien Potencier tout heureux de nous présenter le travail d’un autre que lui, nous a introduit au composant Scheduler avec des slides au titre improbable de “Shampoo Algorithm”. Ce composant est issu d’une proposition de Sergey Rabochiy en juillet 2022 et mergé dans la branche 6.3 de Symfony il y a quelques semaines.

    Et plutôt que de vouloir réinventer cron en le copiant et en essayant de le reproduire en PHP, le composant Scheduler réutilise beaucoup de concepts et de composants Symfony existants pour pouvoir effectuer sa tâche, et à commencer par le composant Messenger.

    Pour l’exemple, nous partirons d’une tâche dont le périmètre est de nettoyer des archives toutes les semaines. Nous voulons du coup avoir le message CleanArchiveMessage dispatché via Messenger et qu’un worker soit en mesure de le traiter. Le périmètre du composant Scheduler sera alors de dispatcher ce message au bon moment.

    Pour cela, le composant Scheduler attend de votre code un Schedule qui liste la ou les tâches programmées et vous fournit une fonction RecurringMessage:every() pour pouvoir facilement programmer la récurrence des messages.

    #[AsSchedule('default')]
    class DefaultSchedule Provider implements ScheduleProviderInterface
    {
        public function getSchedule(): Schedule
        {
            return (new Schedule())
                ->add(RecurringMessage::every('1 week', new CleanArchiveMessage()))
                ;
    }
    

    La fréquence en premier argument ‘1 week’ est un format de date relatif de PHP et qui vous permet d’exprimer cette fréquence avec plein de possibilités, comme par exemple First saturday of next month pour le premier samedi du prochain mois. Le deuxième argument est du coup votre message.

    Le Scheduler va alors se comporter pour Messenger comme un transport synchrone et émettre le message si les conditions de la programmation sont remplies, c'est-à-dire si le moment du prochain message est atteint.

    Pour pouvoir consommer ces messages, vous devez seulement avoir un worker comme c’est déjà le cas pour Messenger mais dédié du coup à ce transport Scheduler.

    bin/console messenger:consume -v scheduler_default
    

    Vous aurez remarqué que vous pouvez du coup avoir plusieurs types de scheduler en les nommant, d’où ici le default, et c’est ainsi que pourrez organiser au mieux vos tâches entre différents schedules suivant votre besoin, voire plusieurs workers si vous en avez besoin. Le Scheduler ne gère pas lui-même d’état pour savoir si le dernier message qui aurait été envoyé l’a bien été ou pour être sûr qu’un seul worker traite le message vous aurez alors besoin de pouvoir cacher l’état et verrouiller l’exécution en faisant appel aux composants Cache et Lock.

    Le périmètre de responsabilité du composant Schedule est alors bien défini : gérer la liste des messages à être envoyés et la date d’envoi du prochain message. Le composant se concentre précisément sur cela et s’appuie sur les autres composants de Symfony pour le reste.

    Pour pouvoir programmer des messages vous pouvez également utiliser des expressions Cron si vous êtes plus habitué, avec RecurringMessage::cron() par exemple

    #[AsSchedule('default')]
    class DefaultScheduleProvider implements ScheduleProviderInterface
    {
        public function getSchedule(): Schedule
        {
            return (new Schedule())
                ->add(RecurringMessage::cron('* 0 * * 0', new CleanArchiveMessage()));
        }
    }
    

    Et évidemment, si ça ne suffit pas, libre à vous d’implémenter votre propre logique pour pouvoir déclencher des messages à une date donnée en écrivant une classe qui doit implémenter l'interface TriggerInterface prévue pour cela.

    Tout cela, et bien plus encore, est très bien décrit dans les slides mais je ne saurais que trop vous conseiller de regarder le replay de la keynote, pas ennuyante du tout par ailleurs, et qui en plus est disponible pour tous du moment que vous êtes connecté.

    Est-ce que le composant Scheduleur va remplacer les crons ? Pas forcément, déjà bien sûr car la résistance au changement est grande. Parce qu'on trouvera bien des cas d'usage que le Scheduler n'aura pas encore prévus comme actuellement le lancement de script ou binaire n'est pas possible.

    Mais le fait de pouvoir intégrer complément dans l'application les tâches programmées est un réel atout. Plus facile à configurer, à déployer, à monitorer, à loguer, les tâches automatisées deviendront partie intégrante de l'application. Il deviendra alors même possible de proposer plus facilement la configuration de ses tâches depuis un backoffice, et pourquoi pas imaginer l'administration des fréquences même.

    Une version 6.3 prometteuse

    En proposant des composants intelligents et offrant aux développeurs la possibilité de se concentrer sur le code métier en laissant le framework s'occuper de ce qui est plus technique au final, Symfony devient de plus en plus attractif dans ses dernières versions. La version 6.3 va apporter son lot d'améliorations dans ce sens et ces nouveaux composants sont de réelles avancées dont les développeurs devraient s'emparer très vite.

    Blog

    Pour continuer votre lecture ...

    Tech

    Forum PHP 2022 : un grand cru !

    Par David Gaussinel 20/10/2022

    Le Forum PHP s'est tenu les 13 et 14 octobre 2022. Petit retour sur ces deux jours de conférences et rencontres devenues depuis plus de 20 ans le rendez-vous à ne pas manquer, et on vous explique pourquoi.

    Lire la suite
    Tech

    Merci de corriger l'erreur 500

    Par David Gaussinel 17/02/2022

    Forcément, vous l'avez déjà croisée ! Vous naviguiez sur un site quelconque, espérons que ça ne soit pas le notre pour le coup, et vous avez eu une page qui affichait une belle erreur 500.

    Lire la suite
    Tech

    Quelle version de Symfony choisir pour son nouveau projet ?

    Par David Gaussinel 30/11/2020

    La question revient à chaque lancement de projet ou avant vente chez Prestaconcept. Quelle version de Symfony pour ce projet ? La dernière long-term support (LTS) ou la dernière version courante sortie ?

    Lire la suite

    Vous avez un projet Laravel ?

    Nous sommes spécialisés en Symfony, et grâce à Web^ID, l’agence sœur du groupe Agile Invest, nous couvrons aussi toute l’expertise Laravel.

    Découvrir Web^ID

    Une question, un projet ?
    Planifiez un échange avec nous !

    Choisissez votre date
    PrestaConcept - Groupe Agile Invest
    5, imp. Morel, 69003 Lyon +33 (0)4 78 54 45 45
    Suivez-nous
    Ecoindex B

    Ce site internet est un site basse consommation. En savoir plus sur l'Ecoindex

    Nos réalisations

  • Logiciel de mise en conformité réglementaire
  • Application de suivi de production des centrales éoliennes
  • Outil d'aide à la décision
  • Portail client
  • Nos métiers

  • Développement sur-mesure
  • Reprise d'application Symfony
  • Expertise Symfony
  • Hébergement & Infogérance
  • Qui sommes-nous

  • PrestaConcept
  • Groupe Agile Invest
  • L'équipe
  • Engagement RSE
  • Blog

  • Tech
  • Méthodologie
  • PrestaConcept
  • RSE
  • © 2025 PrestaConcept
    Mentions légales Politique de confidentialité 🍪
    Retour en haut de page