Fin du transfert

Et voilà, le transfert est terminé.

Lors de ce genre d’opération, il y a des pertes ! Celles-ci sont voulues car j’en ai profité pour réaliser un petit tri vertical !

Vous trouverez donc en haut la liste de mes applications.

Mes projets open-source sont toujours sur GitHub, mes photos sont sur Flickr, la lettre d’actualités n’existe plus car elle ne sortait pas par manque de temps.

Ce ménage réalisé, il me reste à reprendre quelques-un de mes billets de mon ancien blog. Vous les verrez réapparaître ici au fur et à mesure.

A très bientôt !

[POC] Oauth

Vous avez tous vu, au moins une fois, sur un site Internet le bouton de “connexion Facebook” ou “connexion Google ».

Mais qu’y a-t-il derrière ? Dans la grande majorité des cas, il y a le protocole Oauth en version 1.0a ou en version 2.

Je ne vais pas faire d’explication de texte sur le protocole car d’autres s’en sont chargés pour moi et je les en remercie.

Par contre, je vais vous donner un lien vers deux dépôts GitHub qui contiennent les parties utiles pour la mise en oeuvre du protocole avec Symfony2.

La partie serveur Oauth (facebook/google/etc…) et serveur de ressource : https://github.com/macintoshplus/OauthServerApp

La partie cliente (le site Internet) : https://github.com/macintoshplus/OauthClientApp

Pour la partie cliente, il est possible de faire le même travail (connexion de l’utilisateur et récupération de ses informations) de deux manières différentes :

1) en obtenant du serveur de ressource les informations sur l’utilisateur et ne rien stocker en local. Pour cela j’utilise le package « hwi/oauth-bundle ». Il sera nécessaire d’interroger le serveur de ressource pour rafraîchir les données de l’utilisateur connecté.

2) en obtenant du serveur de ressource les informations sur l’utilisateur et les sauvegarder localement. Les informations peuvent donc être utilisées pour relier l’utilisateur à ses données sur votre site. Pour stocker localement les données j’ajoute à « hwi/oauth-bundle » le très populaire « friendsofsymfony/user-bundle ».

Quel est votre retour d’expérience Oauth ?

Personnaliser le nom de la table de l’eventstore de Broadway

Dans le cas fort probable où vous devez personnaliser le nom de la table où Broadway stocke les évènements, voici comment redéfinir le service :

YAML :

my_project.event_store.dbal

     class: Broadway\EventStore\DBALEventStore

     arguments: [@doctrine.dbal.default_connection, @broadway.serializer.payload, @broadway.serializer.metadata, ‘mon_event_store’]

broadway.event_store:

     alias: my_project.event_store.dbal

Vous pouvez également en profiter pour changer la connexion doctrine à la base de données. Attention toutefois, le changement ne s’appliquera pas à la commande d’initialisation de la table. La commande Symfony utilise la connexion « default ».

C’était mon astuce du jour. Et vous, en avez-vous une ?

4 mois avec Broadway

Voilà maintenant 4 mois que j’utilise au quotidien la librairie Broadway pour la gestion de l’EventStore dans un projet en production.

Il y a maintenant plus d’un million d’agrégats et il en est prévu quasiment 5 millions.

Comment cela réagit-il ?

Le système réagit très bien, même en cas de décalage de version entre l’EventStore et le ReadModele.

MS SQL Serveur encaisse plutôt bien la volumétrie, sachant qu’un agrégat a, au minimum, 10 events au cours de sa vie.

Quelles sont les difficultés rencontrées ?

La principale difficulté est liée à l’une des contraintes du projet qui demande l’usage intensif des scripts pour les traitements. Cela nécessite une gestion poussée des transactions SQL afin de limiter les problèmes d’annulation de transaction. En effet, l’EventStore est stocké en base de données et dispose d’une connexion distincte de celle du ReadModel.

Pour le stockage des Events, une transaction ne contient qu’un seul Event (selon le principe de l’Event sourcing, un Event non enregistré ne peut pas être émis sur le bus) alors que la transaction pour le Read Model est enregistrée à la fin du traitement batch effectué sur l’agrégat.

Dans tous les cas, si votre EventStore et votre ReadModel sont dans la même base de données, je vous conseille d’utiliser deux connexions distincte afin d’éviter des problèmes lors de ROLLBACK.

Une autre difficulté rencontrée est la faible résilience du bus de commande. En effet, si le Command Handler ou l’agrégat émet une Exception, les commandes émises ensuite ne seront pas traitées.

Dans mon cas, une commande est envoyée, son traitement dans le Command Handler lève une exception. Le script principal catch l’exception et émet une commande selon la situation. Cette dernière sera mise en file d’attente mais ne sera pas traitée.

Pour contourner le problème, la commande qui lève une exception doit émettre un Event indiquant l’erreur. Charge au script principal de recharger l’agrégat et de vérifier son état.

Il y a sûrement une meilleure méthode pour gérer plus efficacement ces cas. J’attends vos idées dans les commentaires.

Les points positifs ?

Le gros point positif est le suivi de toutes les modifications de l’agrégat tout au long de sa vie. Pouvoir remonter dans le temps et analyser ce qu’il s’est passé est un point très important. La possibilité d’ajouter des informations sur chaque Event est également un plus. Savoir comment a été modifié l’agrégat (ligne de commande ou interface web) et par qui sont parfois des informations très précieuses.

La possibilité de rejouer les événements passés en environnement de développement ou de test est très appréciable. Quoi de mieux que l’utilisation réelle pour vérifier le bon fonctionnement du système?

Est-il envisageable de l’utiliser dans d’autres projets ?

Oui, en utilisant une version stable de la librairie. Mais l’écoute des nouvelles librairies dans le domaine est important.

Quelques liens sur le sujet :

Suite du test de Broadway

La dernière fois, je me suis contenté de mettre en place l’EventStore. Cette fois, il y aura également le ReadModel.

La meilleure méthode est de configurer Saga et le ReadModel de  Broadway avec la valeur « in_memory ». Cela vous laisse toute latitude pour la réalisation de votre ReadModel.

La dernière version de mon exemple ajoute à l’application la partie sécurité. Chaque évènement sera enrichi par l’utilisateur l’ayant commandé.

Pour cela, il a valu mettre en place un MetadataEnricher.

Il est bien évident que vous pouvez réaliser beaucoup de choses avec cette librairie. N’hésitez pas non plus à réaliser un fork (fourche) pour proposer vos améliorations.

Je remercie la société Qualitate.com d’avoir ouvert le code source de sa librairie.

 

Bonus: Un deuxième exemple d’utilisation de la librairie : https://github.com/macintoshplus/school-cqrs-php/tree/broadway

Premier test de Broadway

Même si le nom est peu évocateur d’informatique, le propos est centré sur la mise en œuvre de DDD et des patrons CQRS et EventSourcing.

Vous comptiez que je parle de l’avenue de New York? Certains en parleraient bien mieux que moi.

Cela fait maintenant quelques mois que je me documente sur le Domain Driven Design (développement piloté par le domaine). Dès le début, j’ai été enchanté par la simplicité qu’apporte le langage omniprésent dans le dialogue avec les experts métiers. Les deux parties utilisent les mêmes termes pour désigner la même chose. Pas de transposition, pas de terme technique très obscur pour l’expert métier.

Puis le CQRS est venu avec. Il devient très vite évident tout comme l’utilité de l’EventSourcing. Après plusieurs présentations, lectures (en anglais la plupart du temps), exemples, il fallait commencer la mise en oeuvre.

Mais voilà, je travaille en PHP et la plus grande partie des exemples sont écrits en « .net » et l’un des nombreux langages de Microsoft. Que faire ? Passer au langage de Microsoft ? Ce n’est pas envisageable au travail, et à la maison je suis sur Mac. Il faut trouver des exemples en PHP ou écrire depuis zéro.

Après quelques recherches, j’ai trouvé la librairie lite-cqrs. J’ai passé beaucoup de temps à essayer de comprendre son fonctionnement. Après un fork, beaucoup de modifications et quelques heures de travail, le résultat ne me convenait pas. Il me fallait autre chose de plus consistant.

Puis, au détour d’une question posée sur un réseau social, je découvre la librairie PHP nommée Broadway.

Seulement voilà, Broadway utilise Doctrine/DBAL pour l’EventStore, ElasticSearch pour le ReadModel et Mongo dB pour Saga.

Mes usages seraient plutôt vers un EventStore et un ReadModel dans deux bases de données distinctes.

Mais, avant de tenter l’ajout d’un ReadModel en base de données, j’ai souhaité essayer la mise en place de l’EventSourcing.

Dans mon test, j’ai un agrégat, un command handler (celui qui gère l’exécution des commandes), une commande et un évent.

Après quelques changements dans la configuration de mon application Symfony 2, tout a fonctionné du premier coup!!!

La prochaine fois, je vous parlerai de l’ajout du ReadModel utilisant Doctrine.

Mettre à jour un projet Symfony 2

Dans cet article qui me servira d’aide mémoire, je vais tenter de vous présenter ma méthode de mise à jour d’un projet Symfony 2.

Cette méthode vaut ce qu’elle vaut mais je n’ai rien trouvé de tel sur internet ! Même en anglais.

Plantons le décor

Nous avons un projet qui fonctionne avec Symfony 2.2.11 et nous souhaitons le faire passer sur la version LTS de Symfony 2 soit la version 2.3.x. En effet, la branche 2.2 n’est plus maintenue.

Comme de nombreux projets, j’utilise des librairies et bundles tiers gérés via l’utilitaire Composer.

Avant de rentrer dans le vif du sujet et, comme je compte pouvoir revenir en arrière, je commence par installer mon application dans un nouveau dossier. L’application doit fonctionner parfaitement avant la mise à jour.

Maintenant que nous avons notre application installée, voyons comment mettre à jour les librairies.

Récupération de la version cible

Sur le site de l’éditeur de Symfony, je commence par télécharger la version souhaitée du framework sans les vendors (without vendors).

Dans l’archive, je récupère le fichier « composer.json » afin de le comparer à celui du projet.

Lors de la comparaison, je modifie le fichier « composer.json » de mon projet et modifie les versions des packages.

Mise à jour des librairies tierces

Pour les librairies tierces, j’utilise le site packagist pour vérifier la compatibilité de chaque version utilisée. Au besoin, je recherche la version compatible et je change également la version dans le fichier « composer.json » du projet.

A chaque changement de version pour une librairie tierce, je vérifie que le fonctionnement n’a pas changé. Si c’est le cas, il faudra mettre à jour mon code.

Téléchargement des mises à jour

Dans un terminal, je me place à la racine du site et j’exécute la commande qui peut faire peur :

$ php composer.phar update

Et oui, cette commande va chercher à mettre à jour toutes les librairies. L’exécution est longue et lorsque le téléchargement commence, un soulagement se fait sentir. Aucun conflit n’a été trouvé; ça ne veut pas dire qu’il n’y aura pas d’erreur(s) lors de l’exécution.

Test des nouvelles librairies

Une fois les nouvelles versions téléchargées et installées, commence la phase de débug !

La première chose que je fais est de vider les caches en supprimant les dossiers présents dans le dossier app/cache. Puis, dans la console, j’exécute les commandes suivantes :

$ php app/console cache:warmup

$ php app/console cache:warmup –env=prod

Si aucune erreur n’est présente à ce moment-là, vous n’avez pas d’erreur au niveau des annotations.

Voici celle que j’ai eue :

@Assert\MaxLength(100) est remplacé par @Assert\Length(max=100)

Si vous utilisez le bundle JMS/SerializerBundle et si vous êtes passés de la version 1.x à la version 2.0, les annotations ont changé de place. Il faut donc changer toutes les instructions « use » de vos fichiers.

Maintenant que le kernel démarre, passons aux choses sérieuses.

Avez-vous écrit vos tests unitaires et fonctionnels ? Non, c’est une mauvaise idée mais il n’est pas trop tard pour le faire.

Pour détecter toutes les erreurs, je teste le logiciel dans les moindres détails. A chaque erreur rencontrée, je commence par écrire les tests unitaires et fonctionnels permettant de générer l’erreur. Le test échouera bien sûr mais sera concluant une fois la correction apportée.

Pourquoi perdre du temps à écrire des tests ? Et bien pour en gagner plus tard. Un test écrit pour un bug permet d’éviter son retour !

Car une fois que tous ces tests seront écrits, vous les exécuterez avant chaque livraison pour vérifier que tout fonctionne bien. Il n’est pas exclu qu’un bug passe au travers du filet.

Mise en production

Après quelques heures de travail, le logiciel fonctionne bien. Que reste-il à faire ?

Sauvegarder les corrections du code dans le gestionnaire de codes sources ainsi que les fichiers « composer.json » et « composer.lock ».

Ce dernier est le précieux sésame pour la mise en production. C’est grâce à lui et la commande suivante que l’installation se passera sans problème en production.

$ php composer.phar install –prefer-dist

Mon petit truc pour la mise en production : installer un nouveau site et une fois le nouveau site fonctionnel, réaliser la bascule. Ainsi, la coupure est limitée dans le temps.

D’autre part, j’évite de livrer de nouvelles fonctionnalités avec un changement de version du framework, surtout si elles modifient la base de données. Mais là chacun fait selon ses circonstances.

Bonne mise à jour ! N’hésitez pas à laisser un commentaire sur votre retour d’expérience !