GenServer内部调用宏

时间:2016-11-04 20:26:59

标签: macros elixir

我定义了一个像这样的宏:

defmodule Test do
  defmacro __using__ do
    quote do
      require Test
      import Test
    end
  end

  defmacro my_macro do
    quote do
      Gernserver.call() # generic server call from other module
    end
  end
end

我在我正在构建的lib中包含此代码。在另一个应用程序中测试此lib时,我会在具有use Test

的文件上收到编译错误

错误:exited in: GenServer.call ... exit no process(在my_macro调用的行上,更具体地说是在genserver调用上)。好像genserver没有运行,并不是因为它是编译时间。

将一个简单的Application.ensure_all_started(:lib_name)添加到使用宏似乎可以解决问题。但话说回来,在编译时代码不应该运行,我是对的吗?或者这里是我没有看到的东西?也许我不能在宏上使用genserver调用?

感谢。

1 个答案:

答案 0 :(得分:1)

您在编译阶段TestScheduler中正在调用every

应该将所有计划初始化代码放在一个函数中,在运行阶段中显式调用,或者简单地 引入一个新的GenServer,将其添加到受监管的列表中(以使Elixir在应用启动时自动运行它),并在其every中执行此start_link初始化(或任何其他功能明确地稍后调用):

defmodule Test.Scheduler do
  use GenServer
  use Cronex.Scheduler

  def start_link ... do
    every :minute do
      IO.puts "every minute job"
    end

    every :minute do
      IO.puts "every minute job 2"
    end
  end
end

另一种方式(如果你想让文件保持尽可能干净),将收集every中的数据,而将产生所有调用在运行阶段。

要更熟悉阶段,请将以下代码放入/tmp/test.ex

defmodule A do
  IO.puts "Here “every” macro was called: compilation"

  def a do
    IO.puts "Is not called during compilation stage"
  end
end
IO.puts "=== compilation finished ==="
A.a

问题elixir /tmp/test.ex

Here “every” macro was called: compilation
=== compilation finished ===
Is not called during compilation stage