Journal Notifications d'hébergements pour le Hellfest en Rust

Posté par (page perso) . Licence CC by-sa.
Tags :
23
17
oct.
2019

Sommaire

Le projet

En 2020 je retourne au Hellfest, mais cette fois-ci, avec des proches qui sont PMR. Ils auront donc accès aux plate-formes dédiées, mais en revanche ne peuvent pas se permettre de camper ou dormir sur un lit de camp dans mon hébergement habituel, ni marcher 30 minutes par trajet, avec du dénivelé. Ils ont besoin de trouver un hébergement chez les nombreux particuliers qui en proposent (ça, ce n'est pas très difficile, il y a une plateforme dédiée proposée par le Hellfest : Hellfest Hébergement), mais donc avec une vraie chambre et le plus proche possible du festival, et ça, comme tout ce qui est rare, il ne faut pas le rater.

N'ayant pas tellement envie de still in Memphis le site pour les six prochains mois (étant le seul des trois dont ce n'est pas la première fois, et celui qui les a motivés pour y aller, je suis un peu le référent technique pour organiser cette sortie), et ayant remarqué que le site est une application Angular qui récupère les hébergements en JSON au chargement, je me suis mis en tête de faire un poller qui nous notifierait des nouveaux hébergements qui peuvent nous convenir, pour qu'on puisse aviser si on se jette dessus pour réserver.

Évidemment étant un scalaiste qui ne bluff pas d'après martoni lui-même, j'ai failli partir sur cette solution de facilité. Mais je bave sur Rust depuis quelques années, et moi qui manque d'idées de projets persos sur lesquels tester des choses… c'était l'occasion rêvée.

Vous pouvez consulter le résultat sur HFH-notifier.

J'ai essayé de faire quelque chose de propre : parsing des annonces, sauvegarde des déjà-vus, pretty printing, notification par courriel, jolis logs… je suis assez fier du résultat, mais ça, vous pouvez le tester par vous-même. J'aimerais en revanche discuter avec vous de plusieurs sujets autour de ce projet.

Les enseignements

Rust

Pour un dev Scala

C'est amusant, c'est très ambivalent.

Certains paradigmes sont sans doute bien plus simples à appréhender pour moi (modulo l'adaptation à la syntaxe / l'implémentation d'iceux) ou pour un utilisateur de langage fonctionnel haut niveau, que pour un développeur C ou équivalent. Pattern matching, type Option, monades, fold, map et flatMap and_then, immutabilité par défaut… je suis à la maison.

En revanche…

Le borrow checker, un ami qui vous veut du bien

Évidemment j'ai eu des problèmes avec le borrow checker. Le seul réel problème que je n'ai pas pu résoudre grâce aux messages d'erreur de rustc uniquement, est visible via le changement d'itérateur dans ce commit :

         let wrapper = json.unwrap();
         let interesting = wrapper
             .response
-            .iter()
+            .into_iter()
             .filter(|ad| ad.HFDist < MAX_DISTANCE);

Lorsque plus bas j'essaie de mettre les annonces qui m'intéressent dans ma BDD du pauvre (seen.insert(ad._id, ad);), je me fais insulter par des incantations ésotériques (qui le devenaient souvent d'autant plus que je tentais d'arnaquer le compilo) que j'ai préféré oublier. Je crois que je pouvais m'en sortir en implémentant Clone pour Ad mais pour moi ça sentait la mauvaise solution de contournement : pourquoi ne puis-je pas transférer ces objets dont je n'aurai plus besoin à un nouveau propriétaire ? Je n'ai pas envie de gâcher de la mémoire et du temps pour les copier pour rien (si si, je vous jure, je dev sur la JVM d'habitude).

En résumé de ce que j'ai compris : iter() "laisse" la propriété de chaque élément à la collection qui les contient, quand into_iter() me permet de prendre la propriété (et d'ensuite la donner à la HashMap). Du coup dans le premier cas, à la fin de l'exécution de ma clôture, response étant libéré, les Ad aussi, et ça pète. Je n'ai pas bien compris pourquoi ; pour moi mon intention est claire (je "donne" les annonces à la map) et surtout réalisable (je n'essaie pas d'utiliser les annonces plus loin donc je n'essaie pas d'utiliser une variable que je ne possède plus). Mais bon apparemment ce n'était pas légal.

Au final j'ai un peu mieux compris ces histoires de propriété. J'ai presque envie d'avoir un nouveau projet à écrire pour essayer d'autres constructions plus complexes pour me refaire fesser par le borrow checker. Euh, ça veut dire que j'ai passé le bizutage ? Ça y est, je suis un rustacean ?

AGPL

J'ai failli encore oublier de mettre une licence. Je suis parti sur AGPL car j'aime son idéal de diffusion du partage, et là on ne peut pas dire que ça entre en conflit avec mon business model donc je ne perds pas grand chose (je n'ai pas prévu d'Enterprise Edition). Mais, comme les plus affûtés d'entre vous auront remarqué, je n'ai pas prévu de fichier de configuration pour les variables, et j'ai tordu la bibliothèque de courriel pour s'adapter à la machine par laquelle j'envoie les notifications.

Donc, pour être honnête, j'ai notamment mis les vrais credentials dans le code avant de le compiler et le lancer sur ma machine. Ce qui tourne donc n'est, au sens strict, pas le code que vous pouvez voir. Alors, dans le cas présent, les seuls "clients" qui ont une interaction de cette nature (clientèle) avec mon instance sont mes proches à qui j'envoie les notifications, et je leur fais confiance pour ne pas m'assigner en justice pour réclamer le source avec le mot de passe.

Mais supposons que j'ai poussé mon projet jusqu'à autoriser quiconque à s'inscrire pour être notifié. Pourriez-vous exiger les sources avec le mot de passe ? La licence prévoit-elle un "cas de force majeure", une "nécessité de fonctionnement" comme pour les cookies vitaux qui doivent pouvoir échapper au RGPD ? Aurais-je implémenter la lecture de ces valeurs depuis un fichier / les paramètres du binaire / quoi que ce soit qui me permet de les sortir du code, avant d'oser publier le projet ? Est-ce que les laisser dans le code mais avec un avertissement explicite que ces champs doivent être changés et gardés secrets (via un commentaire, une valeur par défaut write secret here…) suffit ?

Diffuser un poll d'API à la hussarde, est-ce Charlie ?

Pour ceux qui ne s'intéressent pas au Hellfest : c'est un évènement énorme dont la vente des billets est chaotique depuis quelques années et l'explosion de son succès, avec à peu près tous les poncifs de la vente de billet événementielle que vous pouvez imaginer. On a eu de la chance d'avoir nos quatre billets (oui j'ai dit trois plus haut, mais on a un quatrième qui a déjà fait un Hellfest, et puis il est valide comme moi alors on s'en tape). Et même si beaucoup de gens campent au camping fourni, ou retournent dans l'hébergement où ils sont allés aux éditions précédentes, on pourrait facilement imaginer quelques milliers de festivaliers qui souhaitent comme nous trouver le meilleur hébergement. Si tous se compilent leur petite instance et changent la période à quelque chose de trop faible, je peux imaginer que les responsables du site ne soient pas très contents.

Étant donné que je ne publie pas de binaire, la forte adhérence à mon infrastructure (quoique, ça ça ne pètera qu'à l'envoi des courriels, pas au POST…) et la faible configurabilité, c'est quand même assez protégé contre les script kiddies j'espère.

Et en soi, si vraiment une foule de gens écroule HFH, c'est peut-être le signe qu'il y a un besoin de notifications ? Donc, je l'avoue, je n'ai pas proposé mon aide pour implémenter un système équivalent directement dans l'appli d'origine. A ma décharge j'ai cherché un dépôt des sources (vu les principes de partage qui sous-tendent HFH, je m'attendais à trouver un dépôt git quelque part) pour proposer des améliorations (j'ai possiblement quelques idées front aussi) mais je n'ai rien trouvé (je suis plutôt du genre diesel à réfléchir sur les sources et sortir les idées (réalisées) après plutôt que discuter code avant).

Alors si vous comptez utiliser ce projet :

  • soyez raisonnable n'allez pas écrouler HFH en spammant…
  • avant de vous ruer sur un riverain qui propose 4 places à moins d'un kilomètre, si vous n'êtes pas PMR, pensez à Proche 1 et Proche 2 qui sont vraiment hardeux mais qui sont vraiment cassés aussi :-)

Et si vous êtes dev de HFH et êtes fâchés tout rouge :

  • n'hésitez pas à me contacter si ça vous a donné des idées
  • pensez à Proche 1 et Proche 2 avant de me bannir :-)
  • # users.rust-lang.org est là pour t'aider

    Posté par . Évalué à 5 (+5/-1).

    Bonjour,

    Je suis ravi que tu te sois diverti avec Rust. Pour ton erreur du Borrow Checker c'est un peu difficile de t'aider avec les infos que tu donnes. Le plus utile aurait été l'erreur du compilateur elle même.

    A l'avenir je t'invite à parcourir le forum des utilisateurs de Rust et à poster tes questions si la réponse n'y est pas déjà. La communauté Rust est vraiment super.

    Au final j'ai un peu mieux compris ces histoires de propriété. J'ai presque envie
    d'avoir un nouveau projet à écrire pour essayer d'autres constructions plus
    complexes pour me refaire fesser par le borrow checker. Euh, ça veut dire que
    j'ai passé le bizutage ? Ça y est, je suis un rustacean ?

    Sans prétention et sans vouloir te décourager, je pense que tu pourras te considérer rustacean quand tu n'auras plus d'erreurs du Borrow Checker ou que tu seras capable de toutes les corriger en comprenant réellement ce qu'il se passe derrière. Sans doute suis-je médiocre, mais il m'a fallu de longues semaines de pratique avant d'être vraiment à l'aise avec l'ownership, les lifetimes, et quelques subtilités des trait avec l'object safety.

    En revanche une fois le cap passé c'est que du bonheur. Quand je reviens à un autre langage (Go, Python, C++), je vois toutes les horreurs que ces langages laissent faire au développeur à l'insu de leur plein grès et je me sens en grande insécurité.

    • [^] # Re: users.rust-lang.org est là pour t'aider

      Posté par (page perso) . Évalué à 2 (+1/-1).

      Pour ton erreur du Borrow Checker c'est un peu difficile de t'aider avec les infos que tu donnes. Le plus utile aurait été l'erreur du compilateur elle même.

      Bah en fait j'ai trouvé comme j'explique :-D Mais ça n'a pas été évident.

      Dans le commit dont je parle si tu remets .iter() ça donne :

      error[E0597]: `wrapper.response` does not live long enough
        --> src/main.rs:57:27
         |
      46 |       let mut seen = HashMap::new();
         |           -------- lifetime `'1` appears in the type of `seen`
      ...
      57 |           let interesting = wrapper
         |  ___________________________^
      58 | |             .response
         | |_____________________^ borrowed value does not live long enough
      ...
      64 |                   seen.insert(ad._id, ad);
         |                   ----------------------- argument requires that `wrapper.response` is borrowed for `'1`
      ...
      67 |       });
         |       - `wrapper.response` dropped here while still borrowed
      

      J'ai également essayé de faire de seen une HashMap<i32, Ad> au lieu de &Ad mais comme je disais ça revenait à essayer d'arnaquer le checker :

      error[E0507]: cannot move out of `*ad` which is behind a shared reference
        --> src/main.rs:64:37
         |
      64 |                 seen.insert(ad._id, *ad);
         |                                     ^^^ move occurs because `*ad` has type `Ad`, which does not implement the `Copy` trait
      

      Au final comme je disais la solution était into_iter() dont la doc est explicite :

      /// Creates a consuming iterator, that is, one that moves each value out of
      /// the vector (from start to end). The vector cannot be used after calling
      /// this.
      

      Mais encore fallait-il savoir qu'il existe. Je ne sais plus comment j'ai fini par trouver mais c'était au détour d'un message en anglais assez peu explicite. Je me suis dit qu'en en parlant ici, ça ferait une ressource en français pour le suivant :-)

      Sans prétention et sans vouloir te décourager, je pense que tu pourras te considérer rustacean

      Oh c'était surtout pour la blague évidemment. Encore qu'au final je suis assez content de moi, c'est pas un simple Hello World de découverte.

      quand tu n'auras plus d'erreurs du Borrow Checker ou que tu seras capable de toutes les corriger en comprenant réellement ce qu'il se passe derrière.

      Ah par contre là je ne sais pas. Je me considère scalaïste et pourtant je t'assure que je me bats tous les jours contre le compilo et je ne gagne pas toujours :-D

      Quand je reviens à un autre langage (Go, Python, C++), je vois toutes les horreurs que ces langages laissent faire au développeur à l'insu de leur plein grès et je me sens en grande insécurité.

      Ah oui pareil, je ne me vois pas revenir à Java. Ou C ou équivalent si je devais toucher à nouveau à du "bas-niveau".

  • # On vote ?

    Posté par (page perso) . Évalué à 6 (+4/-0).

    Évidemment étant un scalaiste qui ne bluff pas d'après martoni lui-même, […]

    Non tu ne bluff pas

  • # Re:

    Posté par . Évalué à 2 (+1/-0). Dernière modification le 19/10/19 à 00:14.

    un évènement énorme dont la vente des billets est chaotique depuis quelques années

    lol, c'est rien de le dire, un pic de +100000 furieux qui refresh comme des tarés, le serveur n'a plus tenu la charge ! :D

    • [^] # Re:

      Posté par (page perso) . Évalué à 2 (+0/-0). Dernière modification le 19/10/19 à 09:47.

      Un informaticien, soupçonné d'avoir piraté la billetterie en ligne du Hellfest, interpellé en Bretagne

      Si vous ne voulez pas cliquer sur le lien, c'est juste du DDoS a 46 000 connexions

      • [^] # Re:

        Posté par . Évalué à 3 (+2/-0).

        Bah, il voulait juste être sûr que sur ses 46000 connexions, il y en ait au moins une qui rafle les précieux tickets :)

        • [^] # Re:

          Posté par . Évalué à 2 (+0/-0).

          L’article ne dit même pas si ça a réussi.
          Ça aurait été marrant qu’il se retrouve avec 46000 billets. Il aurait peut-être été un peu ennuyé par la facture…

          C’est si difficile que ça d’avoir un billet pour le Hellfest ?

          ¯ : macron (typographie), petit signe diacritique, qui prétend ne pencher ni à gauche ni à droite, mais se place nettement au dessus des vraies lettres, qu’il considère avec mépris.

          • [^] # Re:

            Posté par . Évalué à 1 (+0/-1). Dernière modification le 20/10/19 à 17:42.

            À tous les coups c'est pour les revendre au marché noir.
            Il y a toujours des pigeons pour payer quatre fois le prix d'une entrée ou d'un passe, en particulier quand l’événement lui-même s'est orienté dans la colombophilie.

          • [^] # Re:

            Posté par (page perso) . Évalué à 3 (+2/-1). Dernière modification le 21/10/19 à 11:28.

            C’est si difficile que ça d’avoir un billet pour le Hellfest ?

            Avec au final 6 navigateurs répartis sur 2 ordis je n'ai réussi qu'une fois à avoir un funnel complet (file d'attente puis formulaire d'achat) qui ne plante pas. C'est une sorte de loterie impromptue : peu importe quand tu te connectes dans le créneau de 1-2h, de toute façon la seule chose qui compte c'est : arriveras-tu à soumettre le formulaire d'achat sans te prendre une erreur et perdre ta place ? J'ai commencé en position 27 000 à l'ouverture, donc "normalement" pass garanti, mais finalement file d'attente plantée et retour en position 200 000. Puis sur l'autre ordi, le formulaire de paiement et au moment de payer : erreur 500. Etc etc. Et non je ne me sens pas coupable d'avoir "spammé" avec 6 navigateurs, puisque de toute façon le système étant foireux, c'est la loterie. Et puis quand tu attends poliment dans la file, puis une fois arrivé en position 1 tu arrives sur le formulaire de paiement, et ensuite bah… ça marche pas, bah pas de pitié.

          • [^] # Re:

            Posté par . Évalué à 2 (+1/-0).

            C’est si difficile que ça d’avoir un billet pour le Hellfest ?

            Le problème est que tu te manges souvent des erreurs en pleine tronche :
            4, 3, 2, 1 ! Boom erreur 500, tu met dans le panier, boom erreur 500, tu payes, boom erreur 500, télécharger le ticket, boom erreur 500, etc :)

            Le fait d'attendre 5/10 minutes pour envoyer un formulaire n'est pas dérangeant et franchement ce serait même mieux que de se retrouver bloqué.

            En résumé, en ayant suffisamment de rage et d'acharnement, non ce n'est pas difficile, la preuve j'en ai eu deux :D

      • [^] # Re:

        Posté par (page perso) . Évalué à 2 (+1/-1).

        Vu l'ampleur de l'évènement, et le nombre d'acheteurs légitimes, franchement c'est pas ça le seul problème, et ça sent le presta qui trouve un bouc émissaire (même si évidemment ce type n'a pas aidé…). Il se dit que le Hellfest est très mécontent du presta. C'était le même cirque de file d'attente complètement foireuse l'an dernier alors que d'autres systèmes de vente de tickets encaissent mieux ce genre de charge.

        Mais à la décharge de Weezevent, ils fournissent aussi le système cashless pour les paiements, et ça, ça marche vraiment bien (contrairement au premier système cashless qui avait apparemment été problématique).

  • # Pour aller plus loin

    Posté par . Évalué à 1 (+3/-3).

    Alors là chapeau, autant pour l'idée que pour la réalisation, en plus dans un langage que tu "découvres".

    Petite suggestion d'amélioration possible : Free Mobile propose une API simple permettant d'envoyer des SMS y compris dans son abonnement à 2€ (0€ si tu as une freebox). Si tu as un ordinateur de poche qui fait double SIM ça peut valoir le coup de commander une SIM chez Free et de pousser les annonces par SMS tu gagnerais encore en réactivé.

    Proche 1 et Proche 2 ont intérêt à te payer des bières pour te remercier ! \m/

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.