2017-09-17 4 views
0

Je fais une application maître-ouvrier. Le code maître est le suivant. Ce code appelle de manière asynchrone les travailleurs dans start_link. Une fois que les travailleurs ont terminé leur travail, ils rapportent au maître en utilisant handle_cast appel asynchrone. Après cela, je l'intention de garder l'acteur maître « ON » afin qu'il puisse se reproduire à nouveau les nouveaux travailleurs acteurs (comme il l'a fait dans le premier appel start_link.). Cependant, le maître s'arrête une fois que tous les acteurs travailleurs ont terminé leur travail. Ce poste stackoverflow mentionne l'utilisation de l'appel récursif mais je ne suis pas en mesure de le faire avec Genserver. Y at-il une méthode dans Genserver pour y parvenir?Elixir: boucle l'acteur pour se réexécuter

defmodule Bitcoin.MasterNode do 
use GenServer 

def start_link(opts) do 
    {:ok, pid} = GenServer.start_link(__MODULE__,:ok, opts) 
    start_workers(----perform some task asynchronously----) 
    {:ok, pid} 
end 

def set_message(server, name) do 
    GenServer.cast(server, {:set_message, name}) 
end 

#callbacks 
def init(:ok) do 
    names = [] 
    {:ok, names} 
end 

def handle_cast({:set_message, name},names) do 
    names = names ++ name 
    IO.puts name 
    {:noreply,names} 
end 

fin

Edit: Je application fonctionnant sur le mode i.e., maître distribué est également relié à des noeuds de travail externes. Si Master meurt, les connexions s'éteignent également. L'intention est de garder le noeud maître avec le même PID pour exécuter des temps infinis.

+2

S'il vous plaît ne pas utiliser le code mise en forme pour l'accent, l'utilisation emphase pour l'emphase (vérifiez mes éditions pour voir comment.) – mudasobwa

+0

Vous n'avez pas besoin d'appel récursif pour garder un GenServer en vie. Un GenServer restera en vie jusqu'à ce qu'il soit explicitement arrêté (ou il se bloque en raison d'une erreur). Je ne vois aucun code dans votre fragment de code qui ferait arrêter le GenServer. Est-ce que 'start_workers' arrête ce GenServer? – Dogbert

+2

"L'intention est de garder le noeud maître avec le même PID pour exécuter des temps infinis." - C'est impossible. Utilisez des serveurs nommés à la place. Les noms ne sont pas modifiés avec les redémarrages du serveur. – mudasobwa

Répondre

2

Si je bien compris votre intention, vous voulez recommencer le processus dès que tous les enfants sont faits. Si cela est vrai, il faut utiliser OTP propose au lieu d'inventer leurs propres roues :)

étendre juste l'arbre de supervision avec un autre superviseur, qui supervisera votre « maître » (Bitcoin.MasterNode,) et vous êtes tous ensemble .

Que se passera:

  1. MasterSupervisor commence;
  2. MasterSupervisor commence en toute transparence MasterNode en tant que travailleur avec une stratégie :one_for_one;
  3. MasterNode agit exactement comme il le fait maintenant;
  4. dès que tous les travailleurs ont terminé, MasterNodemeurt, ce qui est bien;
  5. une fois que son enfant MasterNode est mort, MasterSupervisorle redémarrera automatiquement en raison de sa stratégie.

Pour garder une trace de GenServer malgré ayiez été repop ou non, on doit utiliser named servers au lieu d'exploitation PID s:

GenServer.start_link(__MODULE__,:ok, name: MyWorker) 
+0

Mon mauvais. Je veux également que l'application s'exécute en mode distribué. Si le maître meurt, les travailleurs extérieurs mourront aussi. J'ai mis à jour la question. Pouvons-nous encore faire de la magie d'élixir? – COSTA

+0

@mudasobwa: Je suis nouveau à Erlang (et Elixir) et je ne comprends pas complètement le concept des superviseurs. Le superviseur ne devrait pas relancer le processus si le processus * a échoué *, au lieu de réussir. OP a mentionné dans les commentaires que les threads de travail invoquent 'Bitcoin.MasterNode.set_message' avant de mourir, si j'étais à sa place, j'aurais engendré un nouveau processus de' set_message' pour remplacer l'ancien processus. –