Nessuna descrizione

Gildas Chabot acab409b95 fix bold 5 anni fa
README.md acab409b95 fix bold 5 anni fa
index.html 583ae2ce4e add implementation with server sent events 5 anni fa
ms.go b006f332b5 allow for secure protocols 5 anni fa
schema.png 118ecdc59c update README with solution 5 anni fa

README.md

Formulation de l’exercice

Existant :

  • On a un front-end qui communique avec 2 micro services via http ou https pour faire des appels REST.
  • Le front est une SPA et donc c’est du JavaScript
  • Certaines opérations demandées par le front sont asynchrones et demandent plusieurs secondes voir minutes de temps de calcul. Par exemple une demande d’analyse peut lancer 50 simulations qui prennent chaque quelque minutes.

Il y a un nouveau besoin :

  • On doit pouvoir afficher à l’utilisateur le progrès sans qu’il a a faire un refresh de la page (on assume qu’il reste sur la même page).
  • La communication est strictement back->front.

Demande :

  • Quelles sont les approches possibles leurs avantages et inconvénients ?
  • Quelle est l’approche que tu préconises et pourquoi ?
  • Pourrais-tu faire un schéma qui montre ton approche ?

Réponse

Approches possibles

Pour la communication Back->Front, j'ai d'abord pensé aux websockets qui permettent de maintenir un canal de communication bi-directionnel entre le front-end et le back-end, cependant il existe une autre approche, les Server-Sent Events, également définies par le W3C, qui permet d'envoyer des événement et de la donnée depuis le back vers le front. C'est une méthode plus simple et qui a un méchanisme de reconnexion intégré. Le principe des Server-Sent Events est que le navigateur du client fait un appel HTTP au back-end qui commence à répondre immédiatement puis stream, événement par événement, à une cadence définie par le back-end.

Bien que l'idée des Server-Sent Events soit plus vieille que celle des Websockets, ni Edge, ni Microsoft Explorer ne supportent les Server-Sent Events.

Enfin, une alternative qui n'est pas strictement back->front qui a mon avis mérite d'être mentionnée est la technique du polling : le front-end requête régulièrement le back-end pour récupérer le status du traitement. Cette méthode ne permet cependant pas de faire du vrai temps réel, ce qui n'est pas une vrai contrainte pour nous : je suspecte qu'un retard en dessous 1 ou 0.5 seconde ne devrait pas nuire à l'expérience utilisateur.

Côté back-end, 2 alternatives : garder la connexion vivante avec le client durant tout le traitement ou utiliser 2 types de requêtes : un premier qui enregistre la demande de traitement et retourne un identifiant de traitement et un second qui retourne le progrès de ce traitement en cours. La première solution ne peut être raisonnable implémentée que avec les Websockets ; elle est impossible par Polling et fragile avec les Server-Sent Events car on ne sait a priori pas quand le navigateur va décider de renouveler sa connexion. Dans tous les cas, la deuxième solution est plus raisonnable car elle permet à l'utilisateur de suivre la progression du traitement même s'il recharge la page.

Dans ce cas précis, il me semble que le traitement arrive après une phase de configuration donc je suis sûr qu'il existe déjà un identifiant pour ce travail. La demande d'exécution du traitement ne retournera donc pas de nouvel identifiant, elle ne fera que changer l'état du travail.

Enfin, entre le back-end et le process Python, il me semble raisonnable de garder une connexion pendant toute la durée du traitement. Un thread du back-end est dédié à lancer le process Python, à observer le progrès de son exécution et à mettre à jour l'état du travail en fonction du retour. Une alternative serait que le back-end sauvegarde le PID du process Python et que ce dernier écrive dans un fichier temporaire par exemple.

L'approche que je préconise

Je préconise une communication front-back basée sur 2 appels : lancement du traitement (POST HTTP classique) puis récupération du progrès. Pour le progrès, je choisirais Websockets ou Server-Sent Event en discutant avec l'équipe front-end pour voir si une des 2 approche est déjà utilisée sur l'application Javascript ou si l'une de ces 2 méthodes est préférable de leur côté. Pour la gestion du process Python, je préconise qu'un thread back soit dédié à la création et la surveillance de ce process pendant toute son exécution.

Schéma

De droite à gauche : le front-end, dans le navigateur du client, le back-end, le process Python, la base de donnée du back-end.

Le front demande le début du traitement, le back-end lance le traitement, met à jour le status du travail dans sa base de donnée et répond un OK au front-end. En parallèle, le front ouvre un communication back->front (websocket ou server sent events) pour recevoir le progrès en temps réel et le back-end observe le progrès que le Python écrit sur sa sortie standard (par exemple). Dès que le progrès évolue, le back-end envoie un événement du front-end qui peut ainsi mettre à jour sa vue.

Lorsque le process Python s'arrête, le back-end mets à jour le status du travail et informe le front-end que le traitement est terminé. Le front-end peut alors fermer la communication back->front.

schema