1 points par GN⁺ 2023-10-27 | 1 commentaires | Partager sur WhatsApp
  • Flawless est un moteur d’exécution de calculs durables qui aide le code à aller jusqu’au bout même en cas de panne
  • Les workflows s’écrivent comme de simples fonctions Rust, mais sont compilés en WebAssembly plutôt qu’en code natif, puis exécutés dans un environnement déterministe
  • Les effets de bord non déterministes n’apparaissent qu’aux points de contact avec le monde extérieur, comme les requêtes HTTP ou la génération de nombres aléatoires, et Flawless les enregistre dans des logs
  • Si l’exécution est interrompue, Flawless utilise les logs enregistrés pour revenir au même état, sans répéter les effets de bord déjà exécutés
  • Les développeurs peuvent représenter l’état persistant avec le code et les variables locales, sans devoir modéliser eux-mêmes tout l’état dans une base de données, ce qui permet de reprendre après un redémarrage serveur à partir du point d’interruption

Un modèle d’exécution qui exprime l’état persistant dans le code

  • Flawless est un moteur de calculs durables conçu pour exécuter le code jusqu’à son terme, même en cas de panne matérielle ou logicielle
  • Les expériences utilisateur complexes exigent des interfaces et des états complexes, mais il est difficile de modéliser directement tout l’état dans une base de données
  • Les applications modernes ont besoin d’un stockage persistant pour que l’utilisateur ne perde pas sa progression, même s’il recharge la page par erreur
  • Flawless vise à faire modéliser l’état persistant dans le code et les variables locales, afin d’exprimer plus facilement les comportements complexes d’une application

Exécution basée sur WebAssembly et reprise après panne

  • Les workflows sont écrits comme de simples fonctions Rust et peuvent contenir une logique arbitraire
  • Les fonctions sont compilées en WebAssembly plutôt qu’en code natif, puis exécutées dans un environnement entièrement déterministe
  • La non-déterminisme n’est introduit qu’au moment des interactions avec le monde extérieur, comme l’exécution de requêtes HTTP ou la génération de nombres aléatoires
  • Flawless conserve ces logs d’effets de bord non déterministes et les utilise pour la reprise
    • Si l’exécution d’un workflow s’interrompt, il le relance pour rattraper exactement le même état
    • Les effets de bord déjà exécutés ne sont pas rejoués
    • La quantité de données à stocker est minimisée, le reste étant recalculé à la demande en cas de panne
  • Ce modèle d’exécution permet de mieux observer le comportement de l’ensemble du système
    • Il devient possible d’analyser précisément le chemin d’exécution de workflows terminés ou en cours
    • Grâce à l’environnement d’exécution déterministe, les bugs difficiles à reproduire deviennent plus faciles à traiter
  • Les développeurs peuvent réduire la charge liée à la persistance d’état et se concentrer davantage sur la logique métier
  • Même si un redémarrage serveur est nécessaire pour maintenance, il suffit de redémarrer le moteur Flawless pour que les workflows reprennent à partir du point d’arrêt
  • Au 9 décembre 2024, Flawless Beta 3 est disponible

1 commentaires

 
GN⁺ 2023-10-27
Commentaires sur Hacker News
  • Je me demande comment la gestion des versions des workflows est traitée. À mon avis, c’est le problème le plus difficile dans des systèmes comme Temporal/Cadence

    • Je suis l’auteur. Pour des workflows de longue durée, voire pratiquement permanents, je pense que la solution la plus intuitive est d’autoriser des mises à niveau sans interruption
      La mise à niveau ne réussit que si le nouveau code peut rejouer exactement le journal existant des effets de bord. L’idée est de rattraper l’exécution avec le nouveau code, puis de continuer à l’exécuter tel quel une fois le rattrapage terminé
      Si le nouveau code diverge de l’historique existant, la mise à niveau échoue et on revient à l’ancien code. Dans ce cas, une intervention humaine est nécessaire pour vérifier ce qui s’est mal passé
      Il existe d’autres approches, mais en pratique c’est celle qui me semble la plus simple à comprendre et à utiliser. Même pendant le développement, on peut tester si le code diverge en réutilisant les journaux existants
    • Si je comprends bien, le problème consiste à pouvoir mettre à jour un workflow sans casser ceux qui sont déjà vivants et en cours d’exécution
      Est-ce que vous voulez maintenir plusieurs versions en parallèle, ou bien faut-il aussi un moyen de migrer les exécutions en cours vers la dernière définition de workflow ?
    • Exactement. C’est justement le domaine où Conductor gère ça très bien à sa place
  • J’ai l’impression que notre domaine se rapproche de plus en plus de l’architecture ou de la médecine. Grâce à ce genre de technologie, on peut sortir du bricolage pour entrer dans une véritable culture de l’ingénierie
    Pour faire court, je me demande comment on empêche dans ce type de système que l’effet d’une attaque DoS soit persisté

    • La formule « se rapproche de l’architecture et de la médecine » ressemble à un non-sens généré par du machine learning
      L’architecture relève davantage de la gestion d’opinions subjectives sous contraintes réglementaires, et la médecine d’un savoir empirique validé par l’expérimentation. Il est difficile de dire que l’une ou l’autre ressemble vraiment à l’ingénierie
    • Ni l’architecture ni la médecine ne sont des disciplines d’ingénierie, donc je ne vois pas bien pourquoi s’en rapprocher mènerait à une culture de l’ingénierie
      L’architecture est plus proche d’une forme d’art, et les écoles d’architecture sont souvent rattachées aux beaux-arts
      La médecine est une science appliquée comme l’ingénierie, mais ce n’est pas un domaine de l’ingénierie en soi
  • Je me demande si ce déterminisme s’étend aussi aux calculs en virgule flottante
    Dans les jeux multijoueurs, l’état des clients accumulait progressivement une dérive à cause des calculs en virgule flottante, donc il fallait les resynchroniser périodiquement avec l’état du serveur, et historiquement c’était un vrai point douloureux

  • Je me demande où l’état des effets de bord est stocké. Par exemple, si on a une AWS Lambda qu’on veut rendre idempotente, Lambda n’a pas de stockage local persistant entre les exécutions
    À moins de monter quelque chose comme un volume EBS, l’état n’est pas conservé, donc on peut supposer qu’il est stocké dans une base de données ?

    • J’imagine que ce sera la partie payante du produit une fois qu’il sera lancé
  • J’aime bien l’animation qui montre le principe de base et le fonctionnement. Elle est vraiment très bien faite

    • Merci. Je l’ai codée moi-même uniquement en HTML, CSS et JavaScript, et j’y ai mis beaucoup d’efforts et d’affection
      Le code n’est pas très joli, mais l’implémentation est assez intuitive, donc si vous voulez y jeter un œil, c’est ici : https://flawless.dev/js/how-does-it-work-animation.js
    • J’aurais aussi aimé voir un cas d’échec à l’étape d’exécution HTTP, car c’est un point de panne bien plus fréquent à cause des timeouts lors des appels à des endpoints externes
  • Ça a l’air intéressant, mais je me demande si cette façon de marquer une fonction comme ayant des effets de bord est vraiment simple à rendre infaillible
    Dans l’exemple, je suppose que la génération aléatoire est un effet de bord parce qu’elle provient du générateur de nombres aléatoires fourni par flawless. Est-ce que cela aurait aussi été possible avec une fonction Rust ordinaire ?
    J’imagine qu’il doit aussi y avoir une sorte de harnais de test permettant aux développeurs de vérifier leurs workflows

    • Je suis l’auteur de flawless. Avec WebAssembly, on peut rendre ça assez sûr par défaut
      WebAssembly exige de déclarer explicitement les appels à l’hôte dans le module. Si on essaie d’utiliser d’autres appels à l’hôte que ceux fournis par flawless, le module ne peut pas être instancié
      Plusieurs efforts de standardisation sont aussi en cours dans l’écosystème WebAssembly. Par exemple, si on utilise la crate Rust rand puis qu’on compile en WebAssembly, la génération aléatoire passe par des fonctions hôte WASI
      En attendant que wasi, wasi-http et d’autres soient standardisés, nous exposons pour l’instant notre propre interface
      Bien sûr, il y a aussi un gros inconvénient. Tout le code Rust ne peut pas être compilé en WebAssembly. Malgré cela, je pense qu’un mode de refus par défaut qui garantit qu’aucun effet de bord involontaire ne peut jamais se produire est préférable
    • Vu que le générateur aléatoire et les requêtes HTTP sont tous deux sous l’espace de noms flawless, on dirait qu’au lieu de donner accès à tout l’écosystème Rust, il faudra utiliser quelque chose comme std::flawless
      Le harnais résoudra probablement la plupart des problèmes, mais je me demande jusqu’où il sera possible de mapper des fonctionnalités
      Pour l’instant, cela ressemble davantage à un runtime de scripting qui utilise Rust
  • Cela ressemble à une alternative en Rust à Temporal utilisant WASM comme runtime. J’aime beaucoup.
    Je suis le fondateur de windmill.dev, et nous avons nous aussi un moteur durable écrit en Rust. Le nôtre est toutefois bien moins élégant. Nous découpons les workflows en étapes explicites Python/TypeScript/Go/Bash et, pour reprendre à une étape inachevée, nous redémarrons depuis la dernière étape en persistant le résultat de chaque étape dans le jsonb d’une base Postgres
    Les cas d’usage sont clairement différents, et flawless semble suffisamment léger, comme indiqué sur le site, pour modéliser l’état des flux UI et même monter jusqu’à des millions d’instances sur de petits serveurs
    C’est fantastique. J’espère qu’un jour Rust fera tourner tous les systèmes distribués

  • « Tout programme concurrent suffisamment complexe écrit dans un autre langage inclut, comme solution de fortune, une demi-implémentation d’Erlang, boguée, lente et basée sur une spécification non officielle » — première loi de la programmation de Virding

    • L’objectif de Flawless semble être de sauvegarder l’état intermédiaire d’un workflow et, en cas d’échec, de reprendre à partir de ce point
      C’est assez différent d’Erlang. Erlang a surtout été conçu pour développer des logiciels alors qu’on ne disposait que d’équipements prototypes avec de nombreux problèmes matériels
      Pour moi, les deux approches paraissent opposées. Flawless peut se retrouver coincé dans une boucle à tenter d’achever un workflow qui plante en cours de route, alors qu’Erlang peut volontiers jeter 50 % du trafic qui tombe sur un bug matériel
    • Le premier billet de blog mentionne Erlang/OTP : https://flawless.dev/essays/when-letting-it-crash-is-not-eno...
    • Cela ne semble pas du tout résoudre le même problème qu’Erlang
      Erlang le résout essentiellement en éliminant l’état persistant. Presque tout l’état se trouve dans des files de messages ou dans une base externe
      Flawless semble résoudre le problème avec une technique proche du journalisation de système de fichiers, sans être exactement la même. Il enregistre les effets de bord au moment où ils se produisent
      La journalisation de système de fichiers sert à réexécuter après un crash, alors qu’ici l’objectif est d’éviter d’avoir à réexécuter
      On ne voit pas encore clairement dans quels domaines cela conviendra le mieux, mais le recouvrement avec les domaines où Erlang excelle ne semble pas complet
    • https://codesync.global/media/erlangrt-a-beam-vm-reimplement...
    • Dans ce cas, pour qu’un programme bogué basé sur une spécification non officielle dépasse les attentes, il lui suffit d’être rapide
  • Très sympa. Ambient, le runtime de jeu WASM, a un problème similaire. Il y a des processus concurrents et il peut être nécessaire de réessayer les interactions, donc l’approche montrée ici est intéressante
    Je me demande toutefois quelle est la relation avec Lunatic. Lunatic est-il toujours en cours de développement, est-ce un projet annexe, ou est-ce complètement séparé ?
    https://lunatic.solutions/

    • Bonne remarque. C’est réalisé par Bernard Kolobara, CEO et cofondateur de Lunatic
      https://kolobara.com
  • « Imaginez lancer un calcul arbitraire et avoir la garantie que le système s’exécutera jusqu’à son terme et que chaque opération sera effectuée exactement une fois »
    Je me demande comment cela est garanti. Dans un système distribué, la livraison exactement une fois n’est-elle pas impossible ?

    • Au-dessus d’un système de livraison au moins une fois, on peut obtenir un traitement exactement une fois avec des clés d’idempotence
    • Si vous faites référence au théorème CAP, cela demande un peu de contexte supplémentaire : https://www.infoq.com/articles/cap-twelve-years-later-how-th...
    • Ce n’est pas impossible. Il suffit de choisir CP dans le théorème CAP, c’est-à-dire renoncer à la disponibilité
      Si le système peut continuer à avancer, alors les messages sont livrés exactement une fois
      S’il faut une preuve d’existence, NFSv3 faisait déjà fonctionner cela dans les années 1980. Je ne sais pas si c’était le premier
    • Le texte dit « imaginez ». Je ne sais pas d’où vient la phrase citée, et je ne la retrouve pas non plus dans l’original