【问题标题】:Reloading app module doesn't take effect in erlang.mk based app重新加载应用程序模块在基于 erlang.mk 的应用程序中不起作用
【发布时间】:2017-09-11 02:44:05
【问题描述】:

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

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

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

【问题讨论】:

标签: erlang cowboy


【解决方案1】:

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

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

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

模块fragments_app 有一个应用程序行为,调用它只是为了启动和停止应用程序。如果你想应用任何更改,你需要调用它,并确保它被执行,所以你需要调用序列

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

【讨论】:

  • 谢谢@Pascal。这些绝对是有价值的见解。不幸的是,您提供的代码对我不起作用,而且我对 Erlang 的经验不足,无法将您的一般性评论应用于我的具体问题。我得到{error,{not_started,fragments_app}}。我认为它特定于 relx 的工作方式。
  • 你得到的消息意味着应用程序fragments_app还没有启动。我不能说这是否正常。我不习惯 relx,但由于您的 relx.config 仅指片段,也许您应该测试“application:stop(fragments)”和“application:start(fragments)”
猜你喜欢
  • 2019-02-08
  • 1970-01-01
  • 2017-06-30
  • 1970-01-01
  • 2018-05-28
  • 2015-07-01
  • 1970-01-01
  • 2017-02-17
  • 1970-01-01
相关资源
最近更新 更多