Nous avons remporté le deuxième prix du concours Typesafe grâce à l’application Carracedashboard dont l’objectif était de démontrer les possibilités du stack Typesafe. Carracedashboard est une simulation et un suivi en temps réel d’une course automobile. Nous utiliserons cet exemple pour illustrer plusieurs cas d’utilisation d’acteurs Akka pour le développement d’une application web et en quoi la programmation fonctionnelle et l’API Iteratee de Play! rend intuitif le développement d’applications de simulation. Nous montrerons également comment utiliser HTML5 pour améliorer la fluidité des déplacements sur les cartes.
3. De quoi allons nous vous parler ?
• Un concours : Typesafe Developer Contest
• Une application : Car Race Dashboard
• Quelques cas d’utilisation des Actors Akka
et des Iteratees
4. Des patterns pour...
• Effectuer des traitements asynchrones
• Gérer des états dans notre application
• Travailler avec un stream d’événements
5. L’application
Environ 20 heures de travail sur une semaine
scala
coffee
html
Nb
file
Nb
lines
Avg
lines
9
770
86
7
343
49
4
275
68
6. Le résultat
« Fabrice and Antoine have designed an app
that is simply awesome, and a very, very close
runner up to the winner. It’s far more than just a
sample… and the judge were truly wowed»
https://github.com/intechgrp/CarRaceDashboard
10. La course
case class Position(latitude: Double, longitude: Double)
case class TrackPoint(id: Int, position: Position)
type Track = List[TrackPoint]
11. Déplacement des voitures
//return new CheckPoint on the track at distance d from point
private def next(point: TrackPoint, d: Double): TrackPoint
12. La Simulation - CarActor
• Un Acteur Akka par coureur
o
o
Gère l’état courant du coureur : sa position actuelle,
sa vitesse instantanée, la distance parcourue
Réagit à différents messages :
§ “move” : se déplace à la position suivante
§ “start” : début de la course, c.a.d. schedule
l’envoi de messages “move”
§ “getState” : retourne l’état courant
13. La Simulation - RaceActor
• Un Acteur Akka pour gérer tous les coureurs
o
Envoie le message “start” à tous les coureurs au
démarrage de la course : utilisation d’un
BroadcastRouter
router = context.actorOf(Props[CarActor].withRouter(akka.routing.BroadcastRouter(currentRace.get.carActors)))
/ Fire start event : broadcast the event to all CarActors
router ! "start"
15. La Simulation - RaceActor
o
Produit le flux d’événements à partir des CarActor et
le lie au Moteur
// Connect the event stream to the storage actor
new Streams(currentRace.get).events(Iteratee.foreach[models.Events.Event] {
event => models.StorageActor.actor ! event
})
→ pour chaque événement produit par Streams, transmet l’événement au
Moteur (“StorageActor”)
17. Le moteur
• Le moteur est un acteur Akka recevant tous les
•
événements émis par tous les véhicules
Pour chaque événement reçu, l’acteur :
o Publie l’événement sur le stream d’événements
Akka
o Stocke l’événement dans une collection MongoDB
18. Le moteur
• Un autre acteur (StatsActor) est planifié pour calculer
•
•
régulièrement des statistiques (vitesse moyenne, min,
max, …) par voiture
Cet acteur se base sur les données insérées dans
MongoDB
Pour chaque statistique calculée, l’actor publie un
message dans l’eventStream Akka
20. Flux SSE
• Pour chaque navigateur accédant à l’application, un
•
•
acteur « RTEventListener » est créé
Cet acteur est à l’écoute de l’eventStream Akka
Pour chaque message sur ce stream, l’acteur envoie
dans le flux Server Sent Event une représentation
JSON du message
21. Interface
• Au niveau de l’interface HTML5, le flux SSE est
•
connecté avec l’objet JavaScript « EventSource »
Pour chaque message reçu sur ce flux, l’interface est
mise à jour en fonction du type d’événement :
•
•
•
Nouvelle position : déplace la voiture concernée
Statistiques : met à jour le récapitulatif
Vitesse instantée / distance parcourue : met à jour le compteur