Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8

673 views

Published on

Mickaël Rémond présente l'implementation d'une application de chat simple sur le web à l'aide de Phoenix Presence.

Pour réaliser cette application d'exemple, une migration de Phoenix vers Phoenix 1.2 a été effectuée. Toutes les étapes de la migration sont présentés et peuvent aider les développeurs a effectuer les bonnes étapes pour mettre à jour leur application Phoenix.

Published in: Technology
  • Login to see the comments

  • Be the first to like this

Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8

  1. 1. Phoenix Presence: Le service temps réel de Phoenix 1.2 Mickaël Rémond ProcessOne
  2. 2. Brève histoire de Phoenix
  3. 3. Qu'est-ce que Phoenix ? Framework de développement Web Développement lancé en août 2014 avec un focus sur les websockets Inspiration venant de différents frameworks: Ruby on Rails, Clojure Ring, Scala Playframework, ... Version 1.0 sortie en août 2015. Version 1.1 en décembre 2015. Version 1.2 majeure en juin 2016.
  4. 4. Les atouts de Phoenix Points forts: Élégance grâce à la syntaxe d'Elixir et à son système de macros (DSL) Performance et clustering grâce à la VM Erlang Productivité avec des outils de base de données comme Ecto Fonctionnalités: couvre le support des pages web dynamiques. interactions temps réel: websockets et presence.
  5. 5. De Phoenix 1.0 à Phoenix 1.2 Phoenix 1.1: Amélioration des performances des channels Localisation via Gettext Phoenix 1.2: Ecto 2.0 Phoenix Presence
  6. 6. Références Introduction au développement Web avec le framework Phoenix www.youtube.com/watch?v=GPF6w3CsWio(https://www.youtube.com/watch?v=GPF6w3CsWio) Site Web de Phoenix www.phoenixframework.org(http://www.phoenixframework.org)
  7. 7. Websockets, Channels, Presence: Les concepts
  8. 8. Définitions Websockets: protocole de communication entre le navigateur et le serveur. Maintiens la connexion pendant la durée de la session. Channels: Les channels définisset le comportement du serveur pour le broadcast de message en temps réel, par "sujet" (topic). Presence: Le module de "présence tracker synchronize l'état des joins et des leaves de sur les topics, via le module channel, et broadcast les changements.
  9. 9. Architecture
  10. 10. Presence vs Channels ? La fonctionnalité de Phoenix Presence vient sous la forme d'un presence tracker. Il s'agit d'une structure de données en mémoire, répliquée et synchronisée en temps réel sur tous les noeuds d'un cluster Elixir. Elle s'appuie sur les channels: pour recevoir les événements de join et de leave. pour envoyer l'état initial et les mises à jour incrémentales. Phoenix Presence permet: la découverte de service / composants du système. la gestion de la présence des utilisateurs.
  11. 11. Points forts de Phoenix Presence Robustesse: Réplication en temps réel sur l'ensemble du cluster. pas de point de failure unique (SPOF). peut continuer à fonctionner lors d'un netsplit. supporte de fortes charges. Simplicité: de gestion: gère la réconciliation automatiquement lorsque le cluster se reconstitue. de déploiement: dépends uniquement de module standard, sans dépendance externe. d'implémentation: est fourni avec un module Javascript pour faciliter l'implémentation des clients.
  12. 12. Limitations Phoenix Presence est une structure de données distribuée. Les fonctionnalités restent d'assez bas niveau. Il est idéal pour gérer la présence en temps réel pour des communautés: Site web Jeu vidéo Il reste un système simple, fonctionnant sur la base de topic et de channels: Pas de liste de contacts / présence individuelle.
  13. 13. Mise en œuvre
  14. 14. L'exemple Gastronokids Application d'illustration utilisée dans ma précédente présentation sur Phoenix. github.com/ElixirParis/gastronokids(https://github.com/ElixirParis/gastronokids) Enrichissement pour ajouter un module de présence.
  15. 15. Étape 1: Mise à jour de Phoenix 1.0 à Phoenix 1.2
  16. 16. Changements Résumé: Migration vers Postgres: SQLite Ecto ne fonctionne pas encore avec Ecto 2.0 Mise à jour des dépendances Elixir et Javascript Mise à jour vers Ecto 2.0: Model -> Schema Ajout du support de la localisation Gettext Changement du code de gestion des erreurs dans les formulaires Commit complet: Github: Migrate for Phoenix 1.0 to Phoenix 1.2 + move to Postgres (https://github.com/ElixirParis/gastronokids/commit/418e10926c7e647b47628d2006a91123496a57da)
  17. 17. Étape 2: Ajout du module de présence
  18. 18. Générer le code du module Presence Utilisation du scaffolding pour générer le code: $ mix phoenix.gen.presence * creating web/channels/presence.ex Add your new module to your supervision tree, in lib/gastronokids.ex: children = [ ... supervisor(Gastronokids.Presence, []), ] You're all set! See the Phoenix.Presence docs for more details: http://hexdocs.pm/phoenix/Phoenix.Presence.html Nous utilisons le module en l'état.
  19. 19. Configuration
  20. 20. Ajouter le service de présence dans l'application Dans lib/gastronokids.ex, ajout du module dans l'arbre de supervision: def start(_type, _args) do import Supervisor.Spec, warn: false children = [ # Start the endpoint when the application starts supervisor(Gastronokids.Endpoint, []), # Start the Ecto repository worker(Gastronokids.Repo, []), # Presence tracker: supervisor(Gastronokids.Presence, []), ] # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: Gastronokids.Supervisor] Supervisor.start_link(children, opts) end
  21. 21. Config PubSub Vérifier que le service PubSub est bien configuré dans config/config.exs: config :gastronokids, Gastronokids.Endpoint, url: [host: "localhost"], secret_key_base: "j458rtSt4qQnUmBDEVmjX3X6tCtLLjWJy6rhO58WO86s1S2I3i4zePgdcV/T3N41", render_errors: [view: Gastronokids.ErrorView, accepts: ~w(html json)], # This is mapping between name and pubsub backend pubsub: [name: Gastronokids.PubSub, adapter: Phoenix.PubSub.PG2]
  22. 22. room_channel.ex
  23. 23. Lier la présence aux channels (1/2) Importer notre module de présence dans web/channel/room_channel.ex: defmodule Gastronokids.RoomChannel do use Gastronokids.Web, :channel alias Gastronokids.Presence Déclencher un événement de join asynchrone: def join("rooms:lobby", payload, socket) do if authorized?(payload) do send self(), :after_join {:ok, socket} else {:error, %{reason: "unauthorized"}} end end
  24. 24. Lier la présence aux channels (2/2) Garder la trace de la présence après le join et broadcast de la liste initiale: def handle_info(:after_join, socket) do Presence.track(socket, socket.assigns.user_id, %{ device: "browser", online_at: inspect(:os.timestamp()) }) push socket, "presence_state", Presence.list(socket) {:noreply, socket} end Note: Il n'est pas nécessaire de gérer la déconnexion / leave. Channels et Presence gèrent cela pour le développeur.
  25. 25. Broadcast des messages de chat Le callback handle_in sert toujours à assurer la diffusion des messages de chat: def handle_in("new_msg", payload, socket) do payloadWithUser = %{"body" => payload["body"], "user": socket.assigns.user_id} broadcast! socket, "new_msg", payloadWithUser {:noreply, socket} end Le callback handle_out n'est pas nécessaire, car nous utilisons l'implémentation par défaut.
  26. 26. user_socket.ex
  27. 27. Assigner le user_id à la socket Nous étendons la fonction connect/2 dans web/channels/user_socket.ex: def connect(%{"user_id" => id}, socket) do {:ok, assign(socket, :user_id, id)} end
  28. 28. Le client Javascript socket.js
  29. 29. Mise en place socket / présence Dans web/static/js/socket.js, nous importons Socket et Presence, et créons une nouvelle socket: import {Socket, Presence} from "phoenix" let socket = new Socket("/socket", {params: {token: window.userToken, user_id: window.userId}}) Nous lançons la connexion et initialons l'environnement: socket.connect() let channel = socket.channel("rooms:lobby", {}) let presences = {}
  30. 30. Gestion des événements de présence La lib Phoenix Presence Javascript gère l'état des présences pour le développeur: channel.on("presence_state", state => { presences = Presence.syncState(presences, state) render(presences) }) channel.on("presence_diff", diff => { presences = Presence.syncDiff(presences, diff) render(presences) })
  31. 31. Afficher la liste de présence La lib Phoenix Presence Javascript permet de récupérer et trier la liste des présences: let listBy = (id, {metas: [first, ...rest]}) => { first.name = id first.count = rest.length +1 return first } let render = (presences) => { let onlineUsers = Presence.list(presences, listBy) let htmlList = onlineUsers .map(user => `<li>${user.name} (${user.count})</li>`) .join("") userList.html(htmlList) }
  32. 32. Gestion des messages Pour finir, nous gérer la réception et l'envoi des messages: channel.on("new_msg", payload => { var now = new Date(); messagesContainer.append(`<br/>[${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}] ${payload.use }) chatInput.on("keypress", event => { if(event.keyCode === 13){ channel.push("new_msg", {body: chatInput.val()}) chatInput.val("") } })
  33. 33. L'interface utilisateur
  34. 34. Mise en place du code HTML Notre code fournit des éléments conteneurs pour les utilisateurs présents et le chat: <p>Online Users:</p> <ul id="user-list"></ul> <div class="chat"> <div id="messages"></div> <input id="chat-input" type="text"></input> </div> Pour simplifier, le nom de l'utilisateur vient des paramètres de la page: <script> window.userId = "<%= if @conn.params["name"], do: @conn.params["name"], else: "Anonymous" %>" </script>
  35. 35. Démo localhost:4000/?name=Micka%C3%ABl(http://localhost:4000/?name=Micka%C3%ABl) localhost:4000/?name=JohnDoe(http://localhost:4000/?name=JohnDoe) localhost:4000/?name=Steve(http://localhost:4000/?name=Steve)
  36. 36. Télécharger le code Github Gastronokids github.com/ElixirParis/gastronokids(https://github.com/ElixirParis/gastronokids)
  37. 37. Conclusion L'ajout du module de Presence complète les channels de Phoenix de manière redoutablement efficace. Avec cet ajout, Phoenix devient l'outil le plus complet pour implémenter des applications web temps réel reliant: Base de données. Système de templating de pages. Mise à jour temps réel via un outillage Javascript complet. Et tout cela, dans un package unique, sans dépendance.
  38. 38. Thank you Mickaël Rémond ProcessOne mremond@process-one.net(mailto:mremond@process-one.net) http://www.process-one.net/(http://www.process-one.net/) @mickael(http://twitter.com/mickael)

×