2017-04-14 2 views
0

Je construis une application utilisant Erlang.mk avec Cowboy et Sync. La recompilation fonctionne très bien pour la plupart des modules, à l'exception de fragments_app (fragments est le nom de mon projet). J'ai une configuration de routage là et quand je le change (par exemple, ajouter une nouvelle voie) Je reçois une notification de module étant recompilé:Le module d'application de rechargement ne prend pas effet dans l'application basée sur erlang.mk

=INFO REPORT==== 14-Apr-2017::19:56:59 === 
/app/src/fragments_app.erl:0: Recompiled. 

=INFO REPORT==== 14-Apr-2017::19:56:59 === 
fragments_app: Reloaded! (Beam changed.) 

mais le changement ne semble pas être appliquée:

$ http :8080/fragments 
HTTP/1.1 404 Not Found 
content-length: 0 
date: Fri, 14 Apr 2017 19:35:27 GMT 
server: Cowboy 

Module rechargeant également dans la console

c:l(fragments_app). 

ne fonctionne pas, ni exécuter

sync:go(). 

Si j'arrête l'application et la redémarre, cela fonctionne comme prévu. En même temps, les gestionnaires de mise à jour semblent prendre effet immédiatement - la synchronisation est en cours et l'effet se produit sans redémarrer l'application.

Voici la source de fragments_app.erl après le changement:

-module(fragments_app). 
-behaviour(application). 

-export([start/2]). 
-export([stop/1]). 

start(_Type, _Args) -> 
    Dispatch = cowboy_router:compile([ 
    { '_', [ 
     { "/fragments", fragments_http_handler, [] } 
    ]} 
    ]), 
    { ok, _ } = cowboy:start_clear(fragments_http_listener, 100, 
    [{ port, 8080 }], 
    #{ env => #{ dispatch => Dispatch }} 
), 
    fragments_sup:start_link(). 

stop(_State) -> 
    ok. 

Mon Makefile:

PROJECT = fragments 
PROJECT_DESCRIPTION = New project 
PROJECT_VERSION = 0.1.0 

DEPS = cowboy sync 
dep_cowboy_commit = master 

DEP_PLUGINS = cowboy 

SP = 2 

include erlang.mk 

et relx.config:

{release, {fragments_release, "1"}, [fragments, sasl, runtime_tools]}. 
{extended_start_script, true}. 
{sys_config, "rel/sys.config"}. 
{vm_args, "rel/vm.args"}. 
{dev_mode, true}. 

Pourquoi est-ce qui se passe? Tout ce que je peux faire pour appliquer mes modifications sans redémarrer l'application?

+0

Voir ici pour une discussion (en cours): https://twitter.com/lhoguin/status/852986294896664576 –

Répondre

0

Dans Erlang VM, il est possible de charger 2 versions de n'importe quel code de module.

Ensuite, chaque processus continuera à exécuter sa version actuelle jusqu'à ce qu'il appelle une de ses fonctions de module, en utilisant un appel complet: module: fonction (Par ...). Il utilisera dans ce cas la nouvelle version du code. C'est la raison pour laquelle il est utile d'utiliser les comportements OTP qui fournissent un rappel code_change.

La raison en est que chaque processus "peut décider" quand il appliquera la modification, et peut également appeler une fonction pour gérer le changement de version (adaptation de données par exemple).

Le module fragments_app a un comportement d'application, il est appelé uniquement pour mettre en étoile et arrêter l'application. Si vous souhaitez appliquer une modification, vous devez l'appeler et vous assurer qu'elle est exécutée. Vous devez donc appeler la séquence

application:stop(fragments_app), 
application:start(fragments_app), 
... 
+0

Merci @Pascal. Ce sont certainement des idées précieuses. Malheureusement, le code que vous avez fourni ne fonctionne pas pour moi et je n'ai pas assez d'expérience avec Erlang pour appliquer vos remarques générales à mon problème spécifique. J'obtiens '{error, {not_started, fragments_app}}'. Je pense que c'est spécifique au fonctionnement de 'relx'. –

+0

Le message que vous obtenez signifie que l'application fragments_app n'a pas encore démarré. Je ne peux pas dire si c'est normal ou non. Je ne suis pas habitué à relx, mais comme votre relx.config ne fait référence qu'à des fragments, vous devriez peut-être tester "application: stop (fragments)" et "application: start (fragments)" – Pascal