<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
    <generator uri="https://jekyllrb.com/" version="3.9.5">Jekyll</generator>
    <link href="http://publiskills.com/feed.xml" rel="self" type="application/atom+xml"/>
    <link href="http://publiskills.com/" rel="alternate" type="text/html" hreflang="fr" />
    <updated>2024-02-16T01:35:43+00:00</updated>
    <id>http://publiskills.com</id>
    <title type="html">Publiskills - Il est temps de coder !</title>
    <subtitle>Publiskills - Il est temps de coder !</subtitle>
    <author>
        <name>Fabien Wirig</name>
    </author>
    
    
        <entry xml:lang="fr">
    <title type="html">Akka.Net – les fondamentaux</title>
    <link>http://publiskills.com/posts/2018/03/12/akka-net-les-fondamentaux/</link>
    <published>2018-03-12T07:54:12+00:00</published>
    <updated>2018-03-12T07:54:12+00:00</updated>
    <id>http://publiskills.com/posts/2018/03/12/akka-net-les-fondamentaux/</id>
    <content type="html" xml:base="http://publiskills.com/posts/2018/03/12/akka-net-les-fondamentaux/">&lt;h1 id=&quot;akkanet&quot;&gt;Akka.Net&lt;/h1&gt;

&lt;p&gt;Nous avons vu dans l’article précédent (&lt;a href=&quot;/posts/2017/10/06/l-actor-model/&quot; target=&quot;_blank&quot;&gt;Les systèmes réactifs et le pattern actor model&lt;/a&gt;) une présentation du pattern actor model et un exemple de système d’acteurs l’utilisant.&lt;/p&gt;

&lt;p&gt;Nous allons maintenant découvrir une des implémentations de ce pattern : &lt;a href=&quot;https://getakka.net/&quot; target=&quot;_blank&quot;&gt;Akka.Net&lt;/a&gt;. Il s’agit du portage .Net du framework &lt;a href=&quot;https://akka.io/&quot; target=&quot;_blank&quot;&gt;Akka&lt;/a&gt; initialement créé en Scala/Java en 2009.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://getakka.net/&quot; target=&quot;_blank&quot;&gt;Akka.Net&lt;/a&gt; a été développé par &lt;a href=&quot;https://petabridge.com/&quot; target=&quot;_blank&quot;&gt;Petabridge&lt;/a&gt; et permet de créer rapidement des systèmes implémentant le pattern actor model en balayant toute la complexité technique en se concentrant directement sur l’implémentation des comportements de chaque acteur.&lt;/p&gt;

&lt;p&gt;Ce framework permet de créer des systèmes orientés message, scalables, résilients et intrinsèquement distribués.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://getakka.net/&quot; target=&quot;_blank&quot;&gt;Akka.Net&lt;/a&gt; (et toutes ses librairies associées) est disponible via &lt;a href=&quot;https://www.nuget.org/packages/Akka&quot; target=&quot;_blank&quot;&gt;un package nuget&lt;/a&gt;, et supporte .Net standard 1.6.1.&lt;/p&gt;

&lt;h1 id=&quot;tout-acteur-vit-dans-un-actorsystem&quot;&gt;Tout acteur vit dans un ActorSystem&lt;/h1&gt;

&lt;p&gt;Comme l’a dit &lt;a href=&quot;https://en.wikipedia.org/wiki/Carl_Hewitt&quot; target=&quot;_blank&quot;&gt;Carl Hewitt&lt;/a&gt; (concepteur du pattern actor model): &lt;strong&gt;&lt;em&gt;“One actor is no actor, they come in systems”&lt;/em&gt;&lt;/strong&gt;. En &lt;a href=&quot;https://getakka.net/&quot; target=&quot;_blank&quot;&gt;Akka.Net&lt;/a&gt;, ce système est appelé &lt;strong&gt;ActorSystem&lt;/strong&gt;. C’est un univers dans lequel les acteurs s’exécutent et communiquent via des messages.&lt;/p&gt;

&lt;p&gt;Un &lt;strong&gt;ActorSystem&lt;/strong&gt; peut tourner sur une seule machine ou peut être distribué sur plusieurs instances.&lt;/p&gt;

&lt;p&gt;Au sein d’un actorSystem, les acteurs sont répartis dans une hiérarchie. Chaque acteur est rattaché à un parent (y compris le &lt;strong&gt;root guardian&lt;/strong&gt; qui est un cas particulier) dont il dépend et auquel il délègue certaines responsabilités (notamment la gestion des erreurs).&lt;/p&gt;

&lt;p&gt;Pour instancier un actorySystem en C#, il doit être déclaré en lui associant un identifiant:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;
&lt;pre&gt;
&lt;span class=&quot;nf&quot;&gt;ActorSystem&lt;/span&gt; actorSystem = &lt;span class=&quot;nf&quot;&gt;ActorSystem&lt;/span&gt;.&lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;(&quot;MyActorSystem&quot;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/akka-net-init/actor-root.png&quot; alt=&quot;ActorSystem&quot; class=&quot;inline-right-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Lors de l’instanciation d’un actorSystem, plusieurs acteurs sont automatiquement créés (appelés &lt;em&gt;guardians&lt;/em&gt;), ils sont chargés de gérer et maintenir la cohérence de l’ensemble des entités présentes dans l’actorSystem.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;L’acteur &lt;strong&gt;root guardian&lt;/strong&gt; ( &lt;em&gt;/&lt;/em&gt; ) : c’est l’acteur au sommet de l’arborescence. Il est le premier à démarrer et le dernier à s’arrêter lors du cycle de vie de l’actorSystem.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;L’acteur &lt;strong&gt;system guardian&lt;/strong&gt; ( &lt;em&gt;/system&lt;/em&gt; ) : tous les enfants de cet acteur sont des acteurs utiles au bon fonctionnement de l’actorSystem et gérés directement par le framework.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;L’acteur &lt;strong&gt;user guardian&lt;/strong&gt; ( &lt;em&gt;/user&lt;/em&gt; ) : il s’agit du parent de tout acteur instancié par le code utilisant le framework. C’est réellement sous cet acteur que vivra l’ensemble des acteurs que vous allez déclarer.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les guardians sont des acteurs avec lesquels vous n’aurez quasiment jamais à interagir directement. Tout acteur que vous instancierez possèdera donc un chemin (ou &lt;em&gt;path&lt;/em&gt;) qui commencera par le préfixe “&lt;em&gt;/user/&lt;/em&gt;”.&lt;/p&gt;

&lt;h1 id=&quot;conception-dun-acteur&quot;&gt;Conception d’un acteur&lt;/h1&gt;

&lt;p&gt;Pour concevoir un acteur, il est nécessaire de définir une classe héritant du type abstrait &lt;strong&gt;UntypedActor&lt;/strong&gt;. La seule chose à définir est la méthode &lt;strong&gt;OnReceive&lt;/strong&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SimpleUntypedActor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UntypedActor&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnReceive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Traitement pour tout type de message&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;À chaque fois qu’une instance de cet acteur recevra un message, la méthode &lt;strong&gt;OnReceive&lt;/strong&gt; sera invoquée en recevant en argument le &lt;em&gt;message&lt;/em&gt; de type &lt;em&gt;object&lt;/em&gt;. Nous voyons bien que le framework nous permet de nous concentrer sur l’essentiel du comportement d’un acteur : &lt;strong&gt;le traitement des messages qu’il reçoit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Le fait de recevoir des messages de type &lt;em&gt;object&lt;/em&gt; n’est pas très pratique et nous amène très souvent à tester le type réel des messages reçus en utilisant du pattern matching (depuis C#7). Cela génère des déclarations d’acteur ressemblant à :&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;
&lt;pre&gt;
&lt;span class=&quot;k&quot;&gt;public class&lt;/span&gt; SimpleReceiveActor : UntypedActor
{
        &lt;span class=&quot;k&quot;&gt;protected override void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;OnReceive&lt;/span&gt;(&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; message)
        {
                &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt;(message)
                {
                        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Type1&lt;/span&gt; messageType1:
                                &lt;span class=&quot;c1&quot;&gt;// Traitement pour un message de type Type1&lt;/span&gt;
                                &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
                        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Type2&lt;/span&gt; messageType2:
                                &lt;span class=&quot;c1&quot;&gt;// Traitement pour un message de type Type2&lt;/span&gt;
                                &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
                        &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;:
                                &lt;span class=&quot;c1&quot;&gt;// Traitement pour tout autre type de message&lt;/span&gt;
                                &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
                }
        }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Pour simplifier la gestion des messages type par type, la classe &lt;strong&gt;ReceiveActor&lt;/strong&gt; (qui hérite elle-même du type &lt;strong&gt;UntypedActor&lt;/strong&gt;) permet de déterminer une action à exécuter pour chaque type de message reçu.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;
&lt;pre&gt;
&lt;span class=&quot;k&quot;&gt;public class&lt;/span&gt; SimpleReceiveActor : ReceiveActor
{
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SimpleReceiveActor&lt;/span&gt;()
        {
                &lt;span class=&quot;nf&quot;&gt;Receive&lt;/span&gt;&amp;lt;&lt;span class=&quot;kt&quot;&gt;Type1&lt;/span&gt;&amp;gt;(messageType1 =&amp;gt;        &lt;span class=&quot;c1&quot;&gt;/* Traitement pour un message de type Type1   */&lt;/span&gt; );
                &lt;span class=&quot;nf&quot;&gt;Receive&lt;/span&gt;&amp;lt;&lt;span class=&quot;kt&quot;&gt;Type2&lt;/span&gt;&amp;gt;(messageType2 =&amp;gt;      &lt;span class=&quot;c1&quot;&gt;/* Traitement pour un message de type Type2   */&lt;/span&gt; );
                &lt;span class=&quot;nf&quot;&gt;ReceiveAny&lt;/span&gt;(message =&amp;gt;                         &lt;span class=&quot;c1&quot;&gt;/* Traitement pour tout autre type de message */&lt;/span&gt; );
        }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;L’ordre des appels à la méthode générique &lt;strong&gt;Receive&amp;lt;T&amp;gt;&lt;/strong&gt; est important, il détermine dans quel ordre l’acteur va tenter d’identifier quelle action exécuter pour le message en cours de traitement.&lt;/p&gt;

&lt;p&gt;La méthode &lt;strong&gt;ReceiveAny&lt;/strong&gt; permet de définir un comportement pour tout type de message. Lorsqu’elle est utilisée, cette méthode doit bien évidemment être placée à la suite des appels à la méthode &lt;strong&gt;Receive&amp;lt;T&amp;gt;&lt;/strong&gt; car elle intercepte tous les types de messages non déclarés.&lt;/p&gt;

&lt;p&gt;En plus de la méthode &lt;strong&gt;Receive&amp;lt;T&amp;gt;(T message)&lt;/strong&gt;, il existe une méthode &lt;strong&gt;Receive&amp;lt;T&amp;gt;(T message, Predicate&amp;lt;T&amp;gt; predicat)&lt;/strong&gt; permettant de filtrer l’action à exécuter, non seulement par un type donné, mais également par un prédicat spécifique.&lt;/p&gt;

&lt;p&gt;Par exemple :&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;
&lt;pre&gt;
&lt;span class=&quot;k&quot;&gt;public class&lt;/span&gt; SimpleIntReceiveActor : ReceiveActor
{
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SimpleIntReceiveActor&lt;/span&gt;()
        {
                &lt;span class=&quot;nf&quot;&gt;Receive&lt;/span&gt;&amp;lt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&amp;gt;(intVal =&amp;gt; Console.&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;($&quot;{intVal} est pair&quot;),
                                         intVal =&amp;gt; (intVal % 2) == 0);
                &lt;span class=&quot;nf&quot;&gt;Receive&lt;/span&gt;&amp;lt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&amp;gt;(intVal =&amp;gt; Console.&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;($&quot;{intVal} est impair&quot;));
        }
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Il existe également des méthodes &lt;strong&gt;ReceiveAsync&lt;/strong&gt; et &lt;strong&gt;ReceiveAnyAsync&lt;/strong&gt; permettant des traitements asynchrones. Tant que le traitement asynchrone n’est pas terminé, l’acteur reste bloqué et commencera à traiter le prochain message à la fin de la tâche asyncrhone.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mais que se passe-t-il lorsqu’un message est envoyé à un acteur qui ne prend pas en charge ce type de message ? Est-il perdu ? Par exemple si l’on envoie un message de type string à une instance d’un &lt;em&gt;SimpleIntReceiveActor&lt;/em&gt;.
&lt;br /&gt;&lt;br /&gt;
Pas vraiment, il est intercepté par un acteur particulier du framework (&lt;em&gt;DeadLetters&lt;/em&gt;) qui est à l’écoute de ces messages non gérés. Il est possible de s’abonner à cet acteur afin de lui demander de nous transmettre ces messages “perdus”. Nous verrons cela dans un autre article concernant les &lt;em&gt;EventStream&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;instanciation-dun-acteur&quot;&gt;Instanciation d’un acteur&lt;/h1&gt;

&lt;p&gt;Un acteur n’est jamais directement instancié. Il faut demander au framework de l’instancier pour nous. Deux cas sont possibles :&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;
Il s'agit d'un acteur principal, situé juste en-dessous de l'acteur &lt;b&gt;user guardian&lt;/b&gt; ( &lt;i&gt;/user&lt;/i&gt; ):
&lt;br /&gt;Dans ce cas, pour instancier un acteur, il faut appeler la méthode d'extension générique &lt;b&gt;ActorOf&amp;lt;T&amp;gt;&lt;/b&gt; sur l'ActorSystem.
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; actorRef = actorSystem.&lt;span class=&quot;nf&quot;&gt;ActorOf&lt;/span&gt;&amp;lt;&lt;span class=&quot;kt&quot;&gt;SimpleReceiveActor&lt;/span&gt;&amp;gt;(&quot;actorName&quot;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
Il s'agit d'un acteur enfant d'un autre &lt;b&gt;acteur&lt;/b&gt;
&lt;br /&gt;Pour instancier un enfant d'acteur, il faut appeler la méthode d'extension générique &lt;b&gt;ActorOf&amp;lt;T&amp;gt;&lt;/b&gt; sur la propriété &lt;b&gt;Context&lt;/b&gt; de l'acteur parent. Cette propriété est implémentée dans la classe &lt;b&gt;UntypedActor&lt;/b&gt;.
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; actorRef = Context.&lt;span class=&quot;nf&quot;&gt;ActorOf&lt;/span&gt;&amp;lt;&lt;span class=&quot;kt&quot;&gt;SimpleReceiveActor&lt;/span&gt;&amp;gt;(&quot;actorName&quot;);
&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;La classe &lt;strong&gt;ActorSystem&lt;/strong&gt; implémente en réalité l’interface &lt;strong&gt;IActorRefFactory&lt;/strong&gt;, tout comme la propriété &lt;strong&gt;Context&lt;/strong&gt; d’un acteur (&lt;em&gt;IUntypedActorContext&lt;/em&gt;). &lt;strong&gt;ActorOf&amp;lt;T&amp;gt;&lt;/strong&gt; est une méthode d’extension de l’interface &lt;em&gt;IActorRefFactory&lt;/em&gt;. Les deux cas décrits ci-dessus déclenchent donc finalement l’appel à la même méthode.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Le résultat retourné par l’appel à la méthode &lt;strong&gt;ActorOf&amp;lt;SimpleReceiveActor&amp;gt;&lt;/strong&gt; est de type &lt;strong&gt;IActorRef&lt;/strong&gt; et non &lt;strong&gt;SimpleReceiveActor&lt;/strong&gt;.  Comme nous l’avons vu dans l’&lt;a style=&quot;text-decoration:underline;&quot; href=&quot;/2018/01/les-systemes-reactifs-et-le-pattern-actor-model/&quot; target=&quot;_blank&quot;&gt;article précédent&lt;/a&gt;, dans le pattern &lt;em&gt;Actor Model&lt;/em&gt;, les interactions entre acteurs s’effectuent via des références d’acteurs et non via des appels directs aux acteurs. On envoie donc un message à une référence, et pas directement à un acteur.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Un IActorRef est une référence vers un acteur (ou ensemble d’acteurs) instancié(s) par le framework et doit être utilisé pour toute interaction avec un acteur.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;les-props&quot;&gt;Les &lt;em&gt;Props&lt;/em&gt;&lt;/h1&gt;

&lt;p&gt;Mais comment déclarer un acteur possédant un constructeur recevant des paramètres (pour lui injecter des services par exemple) ? C’est là qu’interviennent les &lt;strong&gt;Props&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Il existe, en effet, une autre méthode &lt;strong&gt;ActorOf&lt;/strong&gt; non générique qui reçoit un objet de type &lt;strong&gt;Props&lt;/strong&gt;. Un &lt;strong&gt;Props&lt;/strong&gt; est un objet permettant de définir la façon dont un acteur doit être instancié par le framework. Il est, en quelques sortes, le mode d’emploi pour la création d’un acteur et permet donc de pouvoir spécifier des paramètres pour l’instanciation de ce dernier.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actorProps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SimpleReceiveActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;actorSystem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ActorOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actorProps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;actorName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;communication-entre-acteurs&quot;&gt;Communication entre acteurs&lt;/h1&gt;

&lt;p&gt;Maintenant que nous savons créer des acteurs, voyons comment les faire communiquer entre eux. Plus exactement, voyons comment envoyer des messages à des &lt;strong&gt;IActorRef&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Il existe trois types d’envoi de message : &lt;strong&gt;Tell&lt;/strong&gt;, &lt;strong&gt;Forward&lt;/strong&gt; et &lt;strong&gt;Ask&lt;/strong&gt;.&lt;/p&gt;

&lt;div&gt;
&lt;div class=&quot;table-cell-with-code&quot;&gt;
&lt;ol&gt;&lt;li&gt;
La méthode &lt;strong&gt;Tell&lt;/strong&gt; permet d'envoyer simplement un message à un &lt;em&gt;IActorRef&lt;/em&gt;.
&lt;div class=&quot;code-block highlight&quot;&gt;
&lt;pre&gt;
&lt;span class=&quot;c1 intro&quot;&gt;// Contexte d'exécution : Acteur &quot;a1&quot;&lt;/span&gt;&lt;br /&gt;
a2.&lt;span class=&quot;nf&quot;&gt;Tell&lt;/span&gt;(message);
&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
La méthode &lt;strong&gt;Forward&lt;/strong&gt; permet de transférer un message reçu à un autre &lt;em&gt;IActorRef&lt;/em&gt; en gardant l'expéditeur d'origine en tant qu'émetteur.
&lt;div class=&quot;code-block highlight&quot;&gt;
&lt;pre&gt;
&lt;span class=&quot;c1 intro&quot;&gt;// Contexte d'exécution : Acteur &quot;a2&quot;&lt;/span&gt;&lt;br /&gt;
a3.&lt;span class=&quot;nf&quot;&gt;Forward&lt;/span&gt;(messageReceived); &lt;span class=&quot;c1&quot;&gt; // On transfert le message reçu (initialement envoyé par &quot;a1&quot;) à l'acteur &quot;a3&quot;. &quot;a3&quot; le verra comme ayant été envoyé par &quot;a1&quot;.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;&lt;li&gt;
La méthode &lt;strong&gt;Ask&amp;lt;T&amp;gt;&lt;/strong&gt; est un appel qui permet d'envoyer un message et de rester bloqué en attendant une réponse. Cette méthode est à utiliser avec parcimonie car elle ralentit considérablement la consommation des messages.
&lt;div class=&quot;code-block highlight&quot;&gt;
&lt;pre&gt;
actorRef.&lt;span class=&quot;nf&quot;&gt;Ask&lt;/span&gt;&amp;lt;&lt;span class=&quot;kt&quot;&gt;TypeDeRetour&lt;/span&gt;&amp;gt;(message);&lt;span class=&quot;c1&quot;&gt; // A utiliser avec modération car il s'agit d'appels bloquants !&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&quot;table-cell-when-not-mobile&quot;&gt;
&lt;img src=&quot;/images/posts/akka-net-init/actor-forward.png&quot; style=&quot;max-width:none;margin-left:1rem&quot; alt=&quot;Froward&quot; class=&quot;inline-image&quot; /&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 style=&quot;clear:both;&quot;&gt;&lt;em&gt;Sender&lt;/em&gt; &amp;amp; &lt;em&gt;Self&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;Il existe deux propriétés particulières attachées à un acteur et plus particulièrement à son contexte lors du traitement d’un message. Il s’agit des propriétés &lt;strong&gt;Sender&lt;/strong&gt; et &lt;strong&gt;Self&lt;/strong&gt;, elles sont toutes les deux de type &lt;strong&gt;IActorRef&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Sender&lt;/strong&gt; est un pointeur vers l’acteur ayant émis le message en cours de traitement, il permet de pouvoir échanger avec l’acteur à l’origine du traitement en cours.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Self&lt;/strong&gt; est un pointeur vers l’acteur lui-même. Il permet de planifier un traitement pour lui-même en se renvoyant un message. Ce message sera alors mis en entrée de sa file de messages à traiter. &lt;strong&gt;Self&lt;/strong&gt; permet également à un acteur de transmettre sa référence à d’autres acteurs dans un message.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;les-acteurs-en-tant-que-machine-à-états-finis-final-sate-machine---fsm&quot;&gt;Les acteurs en tant que &lt;em&gt;machine à états finis&lt;/em&gt; (Final Sate Machine - &lt;em&gt;FSM&lt;/em&gt;)&lt;/h1&gt;

&lt;p&gt;Comme nous l’avons vu dans &lt;a style=&quot;text-decoration:underline;&quot; href=&quot;/2018/01/les-systemes-reactifs-et-le-pattern-actor-model&quot; target=&quot;_blank&quot;&gt;l’article sur le pattern actor model&lt;/a&gt;, lors du traitement d’un message, un acteur peut effectuer trois types d’actions :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Créer un ou plusieurs nouveaux acteurs&lt;/li&gt;
  &lt;li&gt;Envoyer un ou plusieurs messages à un nombre fini d’acteurs qu’il connait (y compris lui-même)&lt;/li&gt;
  &lt;li&gt;Changer la façon dont il gèrera les messages suivants&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous avons déjà vu comment créer de nouveaux acteurs et comment envoyer des messages. Nous allons maintenant découvrir comment changer le comportement d’un acteur.&lt;/p&gt;

&lt;p&gt;Pour implémenter ces changements d’état, &lt;a href=&quot;https://getakka.net/&quot; target=&quot;_blank&quot;&gt;Akka.Net&lt;/a&gt; offre une API qui permet de facilement mettre en place les définitions et les transitions entre ces différents états. Il existe deux types de changements de comportement :&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Le remplacement de comportement&lt;/li&gt;
  &lt;li&gt;L’empilement des comportements&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;1-le-remplacement-de-comportement---become&quot;&gt;1. Le remplacement de comportement - &lt;em&gt;Become&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;Pour définir un nouveau comportement, il est possible d’invoquer la méthode &lt;strong&gt;Become&lt;/strong&gt; en lui passant en argument une &lt;em&gt;Action&lt;/em&gt; définissant le comportement à adopter lors du traitement du prochain message.&lt;/p&gt;

&lt;p&gt;Ce nouveau comportement sera alors maintenu jusqu’au prochain appel à la méthode &lt;strong&gt;Become&lt;/strong&gt; qui le remplacera.&lt;/p&gt;

&lt;p&gt;Voyons un exemple simple d’acteur qui utilise la méthode &lt;strong&gt;Become&lt;/strong&gt; :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BiStateActor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ReceiveActor&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BiStateActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// L'acteur traitera le prochain message avec le comportement &quot;HappyActor&quot;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;Become&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HappyActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;HappyActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;ReceiveAny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Tell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;I'm happy :)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;// L'acteur traitera le prochain message avec le comportement &quot;SadActor&quot;&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;Become&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SadActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SadActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;ReceiveAny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Tell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;I'm sad :(&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;// L'acteur traitera le prochain message avec le comportement &quot;HappyActor&quot;&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;Become&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HappyActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Tout d’abord, cet acteur adopte le comportement &lt;em&gt;HappyActor&lt;/em&gt; (affecté dans le constructeur - &lt;span style=&quot;text-decoration:underline;&quot;&gt;ligne 6&lt;/span&gt;).&lt;/p&gt;

&lt;p&gt;Lors de la réception du premier message, cet acteur retournera donc à son expéditeur le message “I’m happy :)” puis changera de comportement pour le message suivant, où il adoptera le comportement &lt;em&gt;SadActor&lt;/em&gt; (&lt;span style=&quot;text-decoration:underline;&quot;&gt;ligne 15&lt;/span&gt;).&lt;/p&gt;

&lt;p&gt;Lors de la réception du message suivant, il retournera donc à son expéditeur le message “I’m sad :(“ puis changera de comportement pour le message suivant en adoptant le comportement &lt;em&gt;HappyActor&lt;/em&gt; (&lt;span style=&quot;text-decoration:underline;&quot;&gt;ligne 25&lt;/span&gt;).&lt;/p&gt;

&lt;p&gt;La boucle est bouclée, nous avons un acteur qui change de comportement à chaque message reçu.&lt;/p&gt;

&lt;h2 id=&quot;2-lempilement-des-comportements---becomestacked-et-unbecomestacked&quot;&gt;2. L’empilement des comportements - &lt;em&gt;BecomeStacked&lt;/em&gt; et &lt;em&gt;UnBecomeStacked&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;Le fonctionnement des méthodes &lt;em&gt;BecomeStacked&lt;/em&gt; et &lt;em&gt;UnBecomeStacked&lt;/em&gt; est similaire au fonctionnement de &lt;em&gt;Become&lt;/em&gt;, à la différence que le nouveau comportement est empilé au-dessus du comportement en cours (&lt;em&gt;BecomeStacked&lt;/em&gt;). Le nouveau comportement est donc adopté, mais il est possible de revenir au comportement précédent en demandant à l’acteur de dépiler son comportement courant (&lt;em&gt;BecomeStacked&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Analysons l’acteur &lt;strong&gt;StackedBiStateActor&lt;/strong&gt; suivant :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StackedBiStateActor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ReceiveActor&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;StackedBiStateActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// L'acteur démarre avec le comportement &quot;HappyActor&quot;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;BecomeStacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HappyActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;HappyActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;ReceiveAny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Tell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;I'm happy :)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;// On empile le comportement &quot;SadActor&quot;. L'acteur aura désormais le comportement &quot;SadActor&quot;&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;BecomeStacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SadActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SadActor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;ReceiveAny&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Tell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;I'm sad :(&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

            &lt;span class=&quot;c1&quot;&gt;// On dépile le comportement en cours (&quot;SadActor&quot;).&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// L'acteur aura donc désormais le comportement précédent (&quot;HappyActor&quot;)&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;UnbecomeStacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Son comportement est exactement le même que l’acteur &lt;strong&gt;BiStateActor&lt;/strong&gt; vu juste avant, il utilise cependant les méthodes &lt;em&gt;BecomeStacked&lt;/em&gt; et &lt;em&gt;UnBecomeStacked&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;L’acteur démarre en empilant le comportement &lt;em&gt;HappyActor&lt;/em&gt; (Étape 1) (&lt;span style=&quot;text-decoration:underline;&quot;&gt;ligne 6&lt;/span&gt;), sa pile de comportements contient donc uniquement le comportement &lt;em&gt;HappyActor&lt;/em&gt; et il retournera “I’m happy :)” lors du traitement de son prochain message (Étape 2).&lt;/p&gt;

&lt;p&gt;Il empilera ensuite le comportement &lt;em&gt;SadActor&lt;/em&gt;  (Étape 3) (&lt;span style=&quot;text-decoration:underline;&quot;&gt;ligne 15&lt;/span&gt;) au-dessus du comportement &lt;em&gt;HappyActor&lt;/em&gt; et retournera “I’m sad :(” à la réception du message suivant (Étape 4).&lt;/p&gt;

&lt;p&gt;Il dépilera ensuite le comportement courant, à savoir &lt;em&gt;SadActor&lt;/em&gt; (Étape 5) (&lt;span style=&quot;text-decoration:underline;&quot;&gt;ligne 26&lt;/span&gt;), et se retrouvera donc avec uniquement le comportement &lt;em&gt;HappyActor&lt;/em&gt; dans sa pile (Étape 6).&lt;/p&gt;

&lt;p&gt;Nous sommes revenus au comportement initial.&lt;/p&gt;

&lt;p&gt;Pour mieux comprendre, voici les étapes :&lt;/p&gt;
&lt;div style=&quot;text-align:center;&quot;&gt;
&lt;img src=&quot;/images/posts/akka-net-init/behaviour-stacks-1.png&quot; alt=&quot;stacked behaviour 1&quot; class=&quot;inline-image&quot; style=&quot;margin:0;&quot; /&gt;&lt;img src=&quot;/images/posts/akka-net-init/behaviour-stacks-2.png&quot; alt=&quot;stacked behaviour 2&quot; class=&quot;inline-image&quot; style=&quot;margin:0;&quot; /&gt;&lt;img src=&quot;/images/posts/akka-net-init/behaviour-stacks-3.png&quot; alt=&quot;stacked behaviour 3&quot; class=&quot;inline-image&quot; style=&quot;margin:0;&quot; /&gt;
&lt;/div&gt;

&lt;h2 id=&quot;3-alors-become-ou-becomestacked--unbecomestacked-&quot;&gt;3. Alors, &lt;em&gt;Become&lt;/em&gt; ou &lt;em&gt;BecomeStacked / UnBecomeStacked&lt;/em&gt; ?&lt;/h2&gt;

&lt;p&gt;Tout dépend de l’acteur que vous implémentez. &lt;em&gt;Become&lt;/em&gt; n’est qu’une particularité de l’utilisation des méthodes &lt;em&gt;BecomeStacked&lt;/em&gt; et &lt;em&gt;UnBecomeStacked&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Lors de l’appel à la méthode &lt;em&gt;Become&lt;/em&gt;, &lt;a href=&quot;https://getakka.net/&quot; target=&quot;_blank&quot;&gt;Akka.Net&lt;/a&gt; utilise en interne la fonctionnalité &lt;em&gt;BecomeStacked&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dans la plupart des cas, &lt;em&gt;Become&lt;/em&gt; suffit, cependant il peut arriver que vous ayez besoin de garder une trace des comportements précédents de l’acteur pour pouvoir, éventuellement, les restaurer par la suite. Dans ce cas, l’utilisation de &lt;em&gt;BecomeStacked/UnBecomeStacked&lt;/em&gt; est votre solution.&lt;/p&gt;

&lt;p&gt;Prenons, par exemple, le cas d’un acteur chargé de gérer le parcours d’un client sur un site d’e-commerce. Le client passe par les comportements &lt;em&gt;Non connecté&lt;/em&gt;, &lt;em&gt;Connecté&lt;/em&gt;, &lt;em&gt;En cours de shopping&lt;/em&gt;, &lt;em&gt;En cours de saisie d’adresse&lt;/em&gt;, &lt;em&gt;En cours de paiement&lt;/em&gt; et là, sa session expire. Il se retrouve alors de nouveau avec le comportement &lt;em&gt;Non connecté&lt;/em&gt;. Lorsque l’utilisateur se reconnecte, ne serait-il pas intéressant de restaurer le comportement &lt;em&gt;En cours de paiement&lt;/em&gt; plutôt que de lui assigner le comportement &lt;em&gt;Connecté&lt;/em&gt; ? Si ces comportements avaient été empilés (&lt;em&gt;BecomeStacked&lt;/em&gt;), il suffirait alors d’invoquer la méthode &lt;em&gt;UnBecomeStacked&lt;/em&gt; pour qu’il retrouve le comportement qu’il avait avant sa déconnexion.&lt;/p&gt;

&lt;h1 id=&quot;mise-en-pratique&quot;&gt;Mise en pratique&lt;/h1&gt;

&lt;p&gt;Le code source d’un projet illustrant tous ces principes est disponible à l’adresse suivante : &lt;a href=&quot;https://github.com/Publiskills/AkkaPlayground&quot; style=&quot;text-decoration:underline;&quot; target=&quot;_blank&quot;&gt;Repository Github AkkaPlayground&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;on-the-next-episodes&quot;&gt;On the next episode(s)…&lt;/h1&gt;

&lt;p&gt;Nous venons de voir les bases de l’utilisation du framework &lt;a href=&quot;https://getakka.net/&quot; target=&quot;_blank&quot;&gt;Akka.Net&lt;/a&gt;. Celui-ci permet d’implémenter facilement une solution basée sur &lt;a href=&quot;/posts/2017/10/06/l-actor-model/&quot; target=&quot;_blank&quot;&gt;le pattern actor model    &lt;/a&gt; en se concentrant directement sur les comportements des acteurs et leur communication.&lt;/p&gt;

&lt;p&gt;Le framework permet de définir les trois types d’actions que peut faire un acteur :
– Créer de nouveaux acteurs via la méthode &lt;strong&gt;ActorOf&lt;/strong&gt; et les &lt;strong&gt;Props&lt;/strong&gt;
– Envoyer des messages via les méthodes &lt;strong&gt;Tell&lt;/strong&gt;, &lt;strong&gt;Forward&lt;/strong&gt; et &lt;strong&gt;Ask&lt;/strong&gt;
– Changer la façon dont il gèrera les messages suivants via les méthodes &lt;strong&gt;Become&lt;/strong&gt;, &lt;strong&gt;BecomeStacked&lt;/strong&gt; et &lt;strong&gt;UnbecomeStacked&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pour continuer notre voyage dans le monde de l’actor model et le framework &lt;a href=&quot;https://getakka.net/&quot; target=&quot;_blank&quot;&gt;Akka.Net&lt;/a&gt;, nous étudierons dans un prochain article, les groupes et les pools d’acteurs.&lt;/p&gt;

&lt;style type=&quot;text/css&quot;&gt;
.table-cell-with-code {
    display:table-cell;
}
.table-cell-when-not-mobile {
    text-align: center;
}
.code-block {
    border-radius: 0.3rem;
    -webkit-border-radius: 0.3rem;
    -moz-border-radius: 0.3rem;
    background: #343642;
    color: #C1C2C3;
    margin: 1em 0;
    padding: 0 1.5rem;
}
.highlight pre {
    font-family: Montserrat;
}
.code-block pre {
    white-space: normal !important;
}
.code-block pre .intro {
    display: inline-block;
    margin-bottom: 0.8rem;
    font-size: 0.9rem;
}
@media (min-width: 600px) {
    .table-cell-when-not-mobile {
        display:table-cell;
        vertical-align: middle;
    }
}
&lt;/style&gt;</content>
    <author>
        <name>Fabien Wirig</name>
    </author>
    <summary>Nous avons vu dans l’article précédent (Les systèmes réactifs et le pattern actor model) une présentation du pattern actor model et un exemple de système d’a...</summary>
    
    
        <media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="akka-net-init/akka-intro-big.jpg" />
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    <category term="Actor model" />
    
    
    <category term="Akka.Net" />
    
    
</entry>
    
        <entry xml:lang="fr">
    <title type="html">Les systèmes réactifs et le pattern actor model</title>
    <link>http://publiskills.com/posts/2017/10/06/l-actor-model/</link>
    <published>2017-10-06T04:53:12+00:00</published>
    <updated>2017-10-06T04:53:12+00:00</updated>
    <id>http://publiskills.com/posts/2017/10/06/l-actor-model/</id>
    <content type="html" xml:base="http://publiskills.com/posts/2017/10/06/l-actor-model/">&lt;h1 id=&quot;les-règles-du-jeu-ont-changé&quot;&gt;Les règles du jeu ont changé&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/evolution.jpg&quot; alt=&quot;Evolution&quot; class=&quot;inline-right-image&quot; /&gt;
Les systèmes informatiques ont énormément évolué au cours de ces dernières décennies. Tant au niveau des capacités disponibles qu’au niveau des performances demandées.&lt;/p&gt;

&lt;p&gt;Les choix d’architecture logicielle étaient précédemment effectués dans un contexte où les infrastructures étaient bien moins flexibles et représentaient des coûts plus importants. Mais les règles du jeu ont bien changé depuis.&lt;/p&gt;

&lt;p&gt;Cet article est le premier d’une série traitant du pattern actor model et des différentes solutions actuellement disponibles pour implémenter des systèmes s’appuyant sur ce passionnant modèle de conception.&lt;/p&gt;

&lt;h2 id=&quot;les-systèmes-réactifs&quot;&gt;Les systèmes réactifs&lt;/h2&gt;

&lt;p&gt;Le besoin de changer de conception est né de la divergence de l’évolution de deux facteurs :&lt;/p&gt;

&lt;h3 id=&quot;--les-sollicitations-et-les-exigences-des-utilisateurs&quot;&gt;- Les sollicitations et les exigences des utilisateurs&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/actor-model-increase.png&quot; alt=&quot;Increasing&quot; class=&quot;inline-left-image&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Le nombre d’accès concurrents (utilisateurs) a explosé au cours des dernières années.&lt;/li&gt;
  &lt;li&gt;La volumétrie des données gérées et stockées a augmenté.&lt;/li&gt;
  &lt;li&gt;Les exigences des utilisateurs en matière de réactivité ne sont plus les mêmes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class=&quot;clear&quot; id=&quot;--les-coûts-et-la-complexité-de-gestion-de-linfrastructure&quot;&gt;- Les coûts et la complexité de gestion de l’infrastructure&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/actor-model-decrease.png&quot; alt=&quot;Decreasing&quot; class=&quot;inline-left-image&quot; /&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Les coûts de l’infrastructure ont drastiquement diminué (RAM, stockage, puissance de calcul…).&lt;/li&gt;
  &lt;li&gt;Les temps de latence des communications réseau se comptent désormais en millisecondes.&lt;/li&gt;
  &lt;li&gt;La complexité de scalabilité des plateformes a été réduite au minimum (IAAS, PAAS).&lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;clear&quot;&gt;Ces évolutions nous ont amenés à repenser les architectures sur lesquelles sont basées nos solutions informatiques actuelles. L’approche réactive se veut très pragmatique, elle définit un ensemble de quatre critères qui doivent être remplis pour pouvoir qualifier un système comme « réactif ».&lt;/p&gt;

&lt;h2 id=&quot;le-reactive-manifesto&quot;&gt;Le reactive manifesto&lt;/h2&gt;

&lt;p&gt;Fort de ces constats, le reactive manifesto définit une approche cohérente afin de tirer profit de ces changements. Selon ce manifeste, un système dit « réactif » doit donc répondre aux 4 critères suivants :&lt;/p&gt;

&lt;h3 id=&quot;1-disponible-responsive--assure-la-réactivité-à-la-sollicitation-sous-toute-condition&quot;&gt;1. Disponible (Responsive) ⇨ &lt;em&gt;assure la réactivité à la sollicitation sous toute condition&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/responsive.jpg&quot; alt=&quot;Responsive&quot; class=&quot;inline-left-image&quot; /&gt;
Le système répond rapidement et de façon constante, dans la mesure du possible, en toutes circonstances. La rapidité et la constance du service fournit par le système en assurent sa pérennité. Cette disponibilité est assurée par les trois autres caractéristiques d’un système réactif.&lt;/p&gt;

&lt;h3 id=&quot;2-résilient-resilient--assure-la-réactivité-face-aux-erreurs&quot;&gt;2. Résilient (Resilient) ⇨ &lt;em&gt;assure la réactivité face aux erreurs&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/resilient.jpg&quot; alt=&quot;Resilient&quot; class=&quot;inline-left-image&quot; /&gt;
La disponibilité du système reste assurée en cas d’erreur au sein d’un de ses composants. L’isolation des composants permet d’éviter la propagation des erreurs. Elles sont gérées localement ou par un composant de supervision.&lt;/p&gt;

&lt;h3 id=&quot;3-souple-elastic--assure-la-réactivité-face-à-la-charge&quot;&gt;3. Souple (Elastic) ⇨ &lt;em&gt;assure la réactivité face à la charge&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/elastic.jpg&quot; alt=&quot;Elastic&quot; class=&quot;inline-left-image&quot; /&gt;
Le système répond rapidement quelle que soit la charge de travail. Il doit être évolutif (scalable) et doit pouvoir s’adapter aux contextes changeants. Cette « élasticité » est rendue possible par la nature « orientée message » du système, qui permet facilement une redistribution des messages.&lt;/p&gt;

&lt;h3 id=&quot;4-orienté-message-message-driven--assure-la-réactivité-face-aux-évènements&quot;&gt;4. Orienté message (Message driven) ⇨ &lt;em&gt;assure la réactivité face aux évènements&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/message-driven.jpg&quot; alt=&quot;Message driven&quot; class=&quot;inline-left-image&quot; /&gt;
Les échanges entre les composants se font par l’échange de messages asynchrones afin de garantir leur faible couplage, leur transparence de localisation et leur isolation.&lt;/p&gt;

&lt;p class=&quot;centered-image&quot;&gt;&lt;img src=&quot;/images/posts/actor-model/reactive-manifesto.jpg&quot; alt=&quot;Le reactive manifesto&quot; /&gt;&lt;/p&gt;

&lt;p&gt;N’hésitez pas à aller consulter (et signer !) &lt;a href=&quot;http://www.reactivemanifesto.org&quot; target=&quot;_blank&quot;&gt;le reactive manifesto&lt;/a&gt; pour de plus amples informations.&lt;/p&gt;

&lt;h1 id=&quot;le-pattern-actor-model-modèle-dacteur&quot;&gt;Le pattern actor model (modèle d’acteur)&lt;/h1&gt;

&lt;h2 id=&quot;un--peu-dhistoire&quot;&gt;Un  peu d’histoire&lt;/h2&gt;

&lt;p&gt;La première approche du pattern actor model a été proposée en 1973 dans la publication “A Universal Modular Actor Formalism for Artificial Intelligence”.
&lt;a href=&quot;https://en.wikipedia.org/wiki/Carl_Hewitt&quot; target=&quot;_blank&quot;&gt;Carl Hewitt&lt;/a&gt;, Peter Bishop et Richard Steiger décrivent alors un modèle permettant de simplifier la gestion des traitements parallèles.
Cette conceptualisation présupposait que le modèle s’exécute dans un réseau de communication dont les latences sont quasiment négligeables.&lt;/p&gt;

&lt;p&gt;De telles performances n’étaient pas disponibles alors, mais les choses ont bien changé depuis.&lt;/p&gt;

&lt;h2 id=&quot;les-concepts-du-pattern-actor-model&quot;&gt;Les concepts du pattern actor model&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;“En informatique, le modèle d’acteur est un modèle mathématique qui considère des acteurs comme les seules fonctions primitives nécessaires pour la programmation concurrente. Les acteurs communiquent par échange de messages.”&lt;/em&gt; (&lt;a href=&quot;https://fr.wikipedia.org/wiki/Mod%C3%A8le_d%27acteur&quot; target=&quot;_blank&quot;&gt;Wikipedia&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Un acteur interagit indirectement avec d’autres acteurs en envoyant des messages à leurs adresses, dont il a sauvegardé les références, sans se soucier de leurs états ou de leurs localisations (processus, machine …).&lt;/p&gt;

&lt;p&gt;Plusieurs adresses peuvent pointer sur un même acteur alors qu’une adresse peut représenter plusieurs acteurs.&lt;/p&gt;

&lt;p&gt;Un acteur dispose d’une file d’attente (mailbox) pour les messages qu’il reçoit. Il traite ces derniers &lt;strong&gt;un par un&lt;/strong&gt; et ne fait donc qu’&lt;strong&gt;un seul traitement à la fois&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Il n’y a &lt;strong&gt;aucune mémoire partagée&lt;/strong&gt; entre les différents acteurs. Les acteurs ne communiquent pas en partageant de la mémoire, mais &lt;strong&gt;ils partagent de la mémoire en communiquant&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Un acteur trouve donc sa raison d’être dans ses interactions avec les autres acteurs. Un acteur n’est jamais seul, il appartient à un système. &lt;strong&gt;“One ant is no ant.”&lt;/strong&gt; (Edward O. Wilson)&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/actor-actions.gif&quot; alt=&quot;Actions possibles&quot; class=&quot;inline-right-image bordered-image&quot; /&gt;
Lors du traitement d’un message, un acteur peut seulement exécuter une ou plusieurs des actions suivantes :&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Créer un ou plusieurs nouveaux acteurs&lt;/li&gt;
    &lt;li&gt;Envoyer un ou plusieurs messages à un nombre fini d’acteurs qu’il connait (y compris lui-même)&lt;/li&gt;
    &lt;li&gt;Changer la façon dont il gèrera les messages suivants&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Un acteur dispose donc d’un nombre limité d’actions possibles lors du traitement d’un message. Il se contente de réaliser la fonction primitive à laquelle il est dédié et de communiquer ses résultats.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Pour résumer, un acteur encapsule :
&lt;img src=&quot;/images/posts/actor-model/actor-composition.jpg&quot; alt=&quot;Composition d'un acteur&quot; class=&quot;inline-right-image bordered-image&quot; /&gt;&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Un état interne isolé des autres acteurs&lt;/li&gt;
    &lt;li&gt;Un comportement (logique primitive de traitement) qui est sa raison d’être&lt;/li&gt;
    &lt;li&gt;Une file d’attente de messages qu’il traite un par un&lt;/li&gt;
    &lt;li&gt;Un protocole de communication avec d’autres acteurs&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;analogies-entre-le-pattern-actor-model-et-la-programmation-orientée-objet-poo&quot;&gt;Analogies entre le pattern actor model et la programmation orientée objet (POO)&lt;/h3&gt;

&lt;p&gt;Ce modèle considère que « tout est acteur ». Cette approche est similaire à l’approche du « tout est objet » de la POO, mais à des niveaux d’abstraction et d’isolation supérieurs.&lt;/p&gt;

&lt;p&gt;Nous pouvons également remarquer les analogies suivantes entre Actor model et POO:&lt;/p&gt;

&lt;table class=&quot;centered-table&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;Pattern actor model&lt;/th&gt;
      &lt;th&gt;POO&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Philosophie&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;Tout est acteur&lt;/td&gt;
      &lt;td&gt;Tout est objet&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Accès à une entité&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;Adresse(s) de l’acteur&lt;/td&gt;
      &lt;td&gt;Instance(s) de l’objet&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Interactions entre entités&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;Envoi de message (non bloquant)&lt;/td&gt;
      &lt;td&gt;Invocation de méthode (bloquant)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Gestion des interactions&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;File d’attente de messages&lt;/td&gt;
      &lt;td&gt;Pile d’appel&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;em&gt;Gestion de la concurrence&lt;/em&gt;&lt;/td&gt;
      &lt;td&gt;Intrinsèque&lt;/td&gt;
      &lt;td&gt;Possible mais très vite complexe&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p&gt;Le pattern actor permet de créer aisément des architectures réactives. De par sa nature intrinsèquement découplée et nativement orientée message, il permet de concevoir des systèmes résilients et aisément scalables.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;présentation-dun-système-dacteurs-complet&quot;&gt;Présentation d’un système d’acteurs complet&lt;/h2&gt;

&lt;p&gt;La théorie est intéressante, mais passons à un exemple concret afin de bien comprendre les possibilités de ce pattern.&lt;/p&gt;

&lt;p&gt;Nous allons ici étudier un système de gestion d’upload d’image sur un site de réseau social.&lt;/p&gt;

&lt;p&gt;Voici la représentation du système d’acteurs mis en place :&lt;/p&gt;

&lt;p class=&quot;centered-image bordered-image&quot;&gt;&lt;img src=&quot;/images/posts/actor-model/actor-system.jpg&quot; alt=&quot;Exemple d'un système d'acteurs&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Trois grandes actions sont réalisées par ce système :&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Validation du contenu (détection des images au contenu inapproprié)&lt;/li&gt;
  &lt;li&gt;Génération des miniatures&lt;/li&gt;
  &lt;li&gt;Agrégation d’informations liées à l’image&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les messages d’upload d’image “ImageUploaded” sont réceptionnés par l’acteur &lt;em&gt;ImageReceiver&lt;/em&gt;, qui se charge de transmettre de nouveaux messages à destination des acteurs suivants (&lt;em&gt;ExplicitContentDetector&lt;/em&gt;, &lt;em&gt;ThumbnailGenerator/ImageFileDispatcher&lt;/em&gt; et &lt;em&gt;ImagePreprocessor&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Ces trois messages déclenchent donc les trois sous-tâches suivantes en parallèle.&lt;/p&gt;

&lt;h3 id=&quot;validation-du-contenu-détection-des-images-au-contenu-explicite&quot;&gt;Validation du contenu (détection des images au contenu explicite)&lt;/h3&gt;

&lt;p&gt;L’acteur &lt;em&gt;ExplicitContentDetector&lt;/em&gt; réalise une analyse de l’image et envoie un message à l’acteur &lt;em&gt;ExplicitContentNotifier&lt;/em&gt; si un contenu inapproprié est détecté.
Si l’image est conforme, il le notifie à l’acteur l’ayant sollicité (&lt;em&gt;ImageReceiver&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;L’acteur &lt;em&gt;ExplicitContentNotifier&lt;/em&gt; prend en charge de publier un message d’alerte “ExplicitContentDetected” (mail, avertissement…) lorsqu’il reçoit une demande de notification.&lt;/p&gt;

&lt;h3 id=&quot;génération-des-miniatures&quot;&gt;Génération des miniatures&lt;/h3&gt;

&lt;p&gt;Si l’image uploadée est trop grande, une demande de redimensionnement est envoyée à l’acteur &lt;em&gt;ThumbnailGenerator&lt;/em&gt;. Dans le cas contraire, le message est directement passé à l’acteur &lt;em&gt;ImageFileDispatcher&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Lorsque l’acteur &lt;em&gt;ImageFileDispatcher&lt;/em&gt; reçoit un message (peu importe la provenance), il transmet un message à l’acteur &lt;em&gt;EnrichedImageFileDispatcher&lt;/em&gt; pour lui signaler la fin de son travail (gestion des miniatures).&lt;/p&gt;

&lt;h3 id=&quot;agrégation-dinformations-liées-à-limage&quot;&gt;Agrégation d’informations liées à l’image&lt;/h3&gt;

&lt;p&gt;Cette partie du système, est en charge de la recherche d’informations, constituée des acteurs &lt;em&gt;ImagePreprocessor&lt;/em&gt;, &lt;em&gt;ImageFilter&lt;/em&gt;, &lt;em&gt;ContentEnricher&lt;/em&gt;, &lt;em&gt;FaceDetector&lt;/em&gt;, &lt;em&gt;UserDataProvider&lt;/em&gt;, &lt;em&gt;ImageDuplicateFinder&lt;/em&gt; et &lt;em&gt;DataAggregator&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;En tout premier lieu, un prétraitement de l’image est effectué en amont par les acteurs &lt;em&gt;ImagePreprocessor&lt;/em&gt; et &lt;em&gt;ImageFilter&lt;/em&gt; pour faciliter l’analyse de l’image.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/actor-model/face-detection.jpg&quot; alt=&quot;Détection d'utilisateurs&quot; class=&quot;inline-right-image bordered-image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Une partie du système prend en charge la détection d’utilisateurs dans les images (&lt;em&gt;FaceDetector&lt;/em&gt;), et l’ajout de leurs informations associées (&lt;em&gt;UserDataProvider&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Il est intéressant de noter que l’acteur &lt;em&gt;FaceDetector&lt;/em&gt; est en réalité exécuté sur plusieurs instances. Il est créé à la volée par le &lt;em&gt;ContentEnricher&lt;/em&gt; afin d’exécuter cette tâche longue et bloquante (une seule action à la fois) sans impacter le reste du système. Il est ensuite détruit une fois son action terminée.&lt;/p&gt;

&lt;p&gt;L’autre partie prend en charge la détection des doublons d’image au sein de l’ensemble des images déjà uploadées (&lt;em&gt;ImageDuplicateFinder&lt;/em&gt;).&lt;/p&gt;

&lt;h3 id=&quot;transmission-du-résultat-de-lanalyse&quot;&gt;Transmission du résultat de l’analyse&lt;/h3&gt;

&lt;p&gt;Enfin, l’ensemble des données récoltées par l’analyse est enfin rattaché à la miniature (&lt;em&gt;DataAggregator&lt;/em&gt; et &lt;em&gt;EnrichedImageFileDispatcher&lt;/em&gt;) généré en parallèle par la partie &lt;em&gt;Géneration des miniatures&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Un message “EnrichedImageValidated” est alors publié vers l’extérieur du système pour notifier celui-ci de la fin du traitement d’une image uploadée.&lt;/p&gt;

&lt;h2 id=&quot;le-pattern-actor-démystifié-par-son-concepteur-en-personne&quot;&gt;Le pattern actor démystifié par son concepteur en personne&lt;/h2&gt;

&lt;p&gt;Je vous laisse regarder cette excellente vidéo dans laquelle son concepteur, &lt;a href=&quot;https://en.wikipedia.org/wiki/Carl_Hewitt&quot; target=&quot;_blank&quot;&gt;Carl Hewitt&lt;/a&gt;, nous présente le pattern actor model. Il y détaille les concepts fondamentaux et la philosophie du modèle (vidéo en anglais) :&lt;/p&gt;

&lt;div class=&quot;youtube-wrapper&quot;&gt;&lt;div class=&quot;youtube-video&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/7erJ1DV_Tlo&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;on-the-next-episodes&quot;&gt;On the next episode(s)…&lt;/h2&gt;

&lt;p&gt;Nous venons de voir en détail la théorie du pattern actor model. Dans un prochain article, je vous présenterai une des implémentations disponibles de ce pattern : Akka.Net.&lt;/p&gt;

&lt;p&gt;Nous y verrons comment mettre en place un système d’acteurs basique puis nous avancerons plus en détail, dans les articles suivants, pour explorer les possibilités et les différentes briques de ce framework (acteurs, testabilité, cluster, streams…).&lt;/p&gt;</content>
    <author>
        <name>Fabien Wirig</name>
    </author>
    <summary>Cet article est le premier d’une série traitant du pattern actor model et des différentes solutions actuellement disponibles pour implémenter des systèmes s’...</summary>
    
    
        <media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="actor-model/intro-image.jpg" />
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    <category term="Actor model" />
    
    
</entry>
    
</feed>