2016-02-16 4 views
4

J'écris une application Erlang qui nécessite d'interroger activement certaines ressources distantes, et je veux que le processus qui fait l'interrogation s'insère dans les arborescences de supervision OTP et prenne en charge toutes les fonctionnalités standard telles que la terminaison correcte, le rechargement de code, etc ...Y at-il un comportement Erlang qui peut agir seul au lieu d'attendre d'être appelé?

Toutefois, les deux comportements par défaut, gen_server et gen_fsm semblent uniquement prendre en charge l'opération basée sur les rappels. En faisant gen_server pour faire cela par des appels à soi-même ou abuser gen_fsm en ayant un seul état qui se boucle toujours avec un timeout 0, mais je ne suis pas sûr que ce soit sûr (ie n'épuise pas la pile ou accumule les messages non lus La boîte aux lettres).

Je pourrais faire mon processus dans un special process et écrire tout ce qui me manipule, mais cela me fait effectivement réimplémenter l'équivalent d'Erlang de la roue.

Y a-t-il un comportement pour du code comme celui-ci?

loop(State) -> 
    do_stuff(State), % without waiting to be called 
    loop(NewState). 

Et sinon, est-il un moyen sûr pour tromper les comportements par défaut en faisant cela sans épuiser la pile ou l'accumulation de messages au fil du temps ou quelque chose?

Répondre

1

Est-il possible que vous puissiez employer un processus essentiellement non OTP? Bien que pour être un bon utilisateur OTP, vous voulez idéalement faire vos processus longs dans gen_server et gen_fsm, parfois vous devez regarder au-delà du livre de règles standard et examiner pourquoi les règles existent. Que se passe-t-il si, par exemple, votre superviseur démarre votre gen_server, et votre serveur gen engendre un autre processus (appelons le processus active_poll), et ils se lient les uns aux autres pour partager le destin (si l'un meurt). Le processus active_poll est désormais supervisé indirectement par le superviseur qui a engendré le serveur_gen, car s'il meurt, le serveur_gen le sera aussi, et tous deux seront redémarrés. Le seul problème que vous avez vraiment à résoudre est la mise à jour du code, mais ce n'est pas trop compliqué - votre serveur gen_server reçoit un appel de rappel code_change lorsque le code doit être mis à jour, et il peut simplement envoyer un message au processus active_poll. un appel de fonction qualifié complet approprié, et bingo, il exécute le nouveau code.

Si cela ne vous convient pas pour une raison quelconque et/ou vous devez utiliser gen_server/gen_fsm/similaires directement ...

Je ne suis pas sûr que l'écriture d'un « processus spécial » vous donne vraiment beaucoup . Si vous avez correctement écrit un processus spécial, de manière à ce qu'il soit en principe compatible avec les principes de conception OTP, il pourrait être inefficace en pratique s'il bloque ou attend une boucle quelque part, et n'appelle pas sys quand il le devrait, vous vraiment au plus une petite optimisation sur l'utilisation de gen_server/gen_fsm avec un timeout nul (ou en ayant un gestionnaire de message asynchrone qui fait l'interrogation et envoie un message à self pour déclencher le prochain sondage). Si tout ce que vous faites pour un sondage actif peut bloquer (comme un socket bloquant lu par exemple), c'est vraiment un gros problème, car gen_server, gen_fsm ou un processus spécial seront tous empêchés de remplir leurs obligations habituelles (qu'ils seraient généralement en mesure soit parce que le rappel dans le cas de gen_server/gen_fsm renvoie, ou parce que receive est appelée et le module sys invoqué explicitement dans le cas d'un processus spécial).Si ce que vous faites pour interroger activement n'est pas bloquant, vous pouvez le faire, mais si vous interrogez sans délai, il devient effectivement occupé (ce n'est pas tout à fait parce que la boucle inclura un appel de réception quelque part, ce qui signifie que le processus va céder, donnant au planificateur l'opportunité volontaire d'exécuter d'autres processus, mais ce n'est pas très loin, et il s'agira toujours d'un cochon CPU relatif). Si vous pouvez avoir un délai de 1ms entre chaque sondage qui fait un monde de différence par rapport à l'interrogation aussi rapidement que vous le pouvez. Ce n'est pas idéal, mais si vous le devez, ça va marcher. Utilisez donc un timeout (aussi gros que possible sans que cela ne devienne un problème), ou ayez un gestionnaire de message asynchrone qui effectue l'interrogation et envoie un message à self pour déclencher le prochain sondage.