重新加载应用程序模块不会';t在基于erlang.mk的应用程序中生效

重新加载应用程序模块不会';t在基于erlang.mk的应用程序中生效,erlang,cowboy,Erlang,Cowboy,我正在使用Erlang.mk与Cowboy和Sync构建一个应用程序。除了fragments\u app(fragments是我项目的名称)之外,重新编译对于大多数模块都非常有效。我在那里有一个路由配置,当我更改它(例如添加新路由)时,我会收到一个关于正在重新编译模块的通知: =INFO REPORT==== 14-Apr-2017::19:56:59 === /app/src/fragments_app.erl:0: Recompiled. =INFO REPORT==== 14-Apr-2

我正在使用Erlang.mk与Cowboy和Sync构建一个应用程序。除了
fragments\u app
(fragments是我项目的名称)之外,重新编译对于大多数模块都非常有效。我在那里有一个路由配置,当我更改它(例如添加新路由)时,我会收到一个关于正在重新编译模块的通知:

=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).
没用,也没用

sync:go().
如果我停止应用程序并再次启动它,它将按预期工作

同时,更新处理程序似乎立即生效-同步正在接收它,并且在不重新启动应用程序的情况下生效

以下是更改后
fragments\u 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.
我的生成文件:

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

为什么会这样?我能做些什么来应用我的更改而不重新启动应用程序?

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

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

这样做的原因是,每个流程“可以决定”何时应用更改,还可以调用函数来管理版本更改(例如,数据自适应)

模块
fragments\u app
具有应用程序行为,调用该模块仅用于启动和停止应用程序。如果希望应用任何更改,则需要调用它,并确保它已执行,因此需要调用序列

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

请参见此处了解一些(正在进行的)讨论:谢谢@Pascal。这些绝对是有价值的见解。不幸的是,您提供的代码不适合我,我对Erlang没有足够的经验,无法将您的一般评论应用到我的具体问题中。我得到
{error,{not_start,fragments_app}}
。我认为这是特定于
relx
的工作方式。您收到的消息意味着应用程序尚未启动。我不能说这是否正常。我不习惯relx,但是由于您的relx.config只引用片段,也许您应该测试“application:stop(fragments)”和“application:start(fragments)”