2017-04-14 40 views
0

我正在用Cowboy和Sync构建使用Erlang.mk的应用程序。除了fragments_app(片段是我的项目的名称)外,重新编译对于大多数模块都非常有效。我有一个路由配置那里,当我改变它(如增加新航线),我得到一个关于模块通知被重新编译:重新加载应用程序模块不会在基于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.) 

但变化似乎并不适用:

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

在控制台

c:l(fragments_app). 

没有帮助,也不执行

也重装模块

如果我停止应用程序并重新启动它,它将按预期工作。

与此同时,更新处理程序似乎立即生效 - 同步正在选取它并在不重新启动应用程序的情况下生效。

这里是fragments_app.erl变更后的源:

-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. 

我的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 

和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}. 

这究竟是为什么?我可以做什么来应用我的更改,而无需重新启动应用程序?

+0

在这里看到一些(进行中)的讨论:https://twitter.com/lhoguin/status/852986294896664576 –

回答

0

在Erlang VM中,可以加载任何模块代码的2个版本。

然后,每个进程将继续执行其当前版本,直到使用完全限定的调用调用其模块函数之一:module:function(Par ...)。它将在这种情况下使用新的代码版本。 这就是为什么使用OTP行为提供code_change回调有用的原因。

原因是每个进程“可以决定”何时应用更改,还可以调用一个函数来管理版本更改(例如数据适配)。

模块fragments_app有一个应用程序行为,它只被称为明星和停止应用程序。如果你想被应用于任何改变,你需要调用它,并确保其执行,所以你需要调用序列

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

谢谢@Pascal。这些绝对是有价值的见解。不幸的是,你提供的代码对我来说不起作用,而且我对Erlang没有足够的经验来将你的一般评论用于我的具体问题。我得到了'{error,{not_started,fragments_app}}'。我认为这是'relx'的具体做法。 –

+0

您收到的消息意味着应用程序fragments_app尚未启动。我不能说这是否正常。我不习惯relx,但是因为你的relx.config只引用片段,所以你应该测试“application:stop(fragments)”和“application:start(fragments)” – Pascal

相关问题