• [^] # Re: Rx

    Posté par . En réponse au journal La programmation concurrente en mode Goto. Évalué à 3.

    Pour moi l'asynchrone est un mécanisme de programmation parallèle au même titre de la concurrence. Dans le premier cas (l'asynchrone) un seul traitement est réalisé à un moment donné contre plusieurs dans le second (et encore, à condition d'avoir plusieurs cœurs physiques...), mais ça c'est justement des détails et pas un besoin fonctionnel.

    Tu te contredis entre ta première et ta seconde phrase... L'asynchrone est un pattern qui découple temporellement une portion de code et celle qui l'a appelé. Le fait que ce soit parallèle n'est pas une obligation (c'est ce qui se passe quand on utilise POE par exemple).

    Si une des deux branches se plante ça veut dire qu'on est dans un état qui mérite un traitement particulier, ça peut être arrêter toutes les coroutines jusqu'à un certain niveau, retenter de zéro la traitement de la coroutine ayant échoué et bien encore ne rien etc.

    Ce genre de besoin devrait amha se gérer via des commandes. Tu crée des commandes et tu choisi leur comportement en cas de problème, leur timeout, etc. Ça permet de gérer les choses dans un contexte plus concis, tu ne viens pas demander à l'appelant de gérer cela.

    Ensuite effectivement une fois qu'on sait ce qu'on doit arrêter, encore faut-il le faire proprement. À ce niveau trio injecte une exception CancelledError dans la coroutine à terminer, ce qui permet à celle-ci de se nettoyer proprement, voir même d'annuler son arrêt si le cœur lui en dit (mais encore une fois ça dépend totalement du cas d'usage).

    Les exceptions sont déjà complexe à gérer là ça signifie que n'importe où une exception invisible peut subvenir ? Si ça intervient dans le code d'une bibliothèque ça se passe comment ? La seule façon de survivre correctement à cela est d'avoir un code très défensif et perso ça ne me plaît pas des masses d'écrire ce genre de code.

    j'imagine que tu parles de twisted ?

    Effectivement.

    Je n'ai pas compris ce que tu voulais dire par contexte principal ? Dans un framework asynchrone lambda une fois l'event loop lancée il n'y a pas une coroutine plus principale qu'une autre. Et de toute façon l'event loop en question passe déjà son temps à switcher d'une coroutine à une autre donc je ne vois pas en quoi aller dans un contexte supplémentaire serait intenable...

    On parle de lever d'exception. Lever une exception c'est manipuler l'état de ton contexte. La façon normale de remonter une erreur dans une event loop c'est de lui publier un évènement d'erreur. Le problème n'est pas le switch, mais le fait de remonter un comportement par une manipulation de l'état.

    C'est justement la force des nursery, cela te permet de créer des scope regroupant tes coroutines. Et donc De fait quand une coroutine plante ça remonte ton arbre de scopes (en arrêtant les coroutines en bonne ordre dans la foulée) jusqu'à ce que un try/except veuille bien s'en occuper. Si personne ne veut s'en occuper, ben ton programme crash. Et c'est bien normal, explicit is better than implicit comme ils disent.

    Cette remontée est une fuite de ton scope, là où un passage de message ferrait l'affaire. Quant à l'explicite, je ne pense pas qu'injecter une exception comme tu as l'air de le décrire soit explicite. Si tu écris une méthode et qu'elle est finalement utilisée dans une tâche nursery, il sera impossible de voir dans le code de cette méthode qu'il manque potentiellement la gestion de cette dernière.

    Tout à fait d'accord. Malgré tout c'est parfois difficile de travailler uniquement avec un système de messages (typiquement dans le cas d'une base de donnée qui doit pouvoir traiter plusieurs requêtes en parallèle alors que celles-ci travaillent sur les mêmes données).

    Toutes les bases de données ont déjà résolues se problème par la création d'un event log. Ça fige l'ordre des actions (et ça apporte un tas d'autres propriété sympa). Un event log c'est justement pour rester dans un système à message et ne manipuler un état que lorsque les évènements qui l'ont composés sont triés et rejouables. Au contraire, gérer une base de données par modification directe de l'état du système (ce que fait une levée d'exception) impose de gérer un lock global pour serialiser les opérations.

    Merci pour la discussion je la trouve enrichissante (ainsi qu'à Yves et Galndos).