简体   繁体   English

在 elixir 混合任务中使用 melpon/memoize

[英]using melpon/memoize in elixir mix task

I am using melpon/memoize for cache in my phoenix aplication.我在我的凤凰应用程序中使用melpon/memoize进行缓存。 It is working very well in runtime.它在运行时运行良好。

However, I have a few mix tasks in my application, which I execute sparingly.但是,我的应用程序中有一些混合任务,我很少执行。 Now these tasks eventually call a memoized function, for example:现在这些任务最终调用了一个memoized function,例如:

defmodule Mix.Tasks.MyTask do
  use Mix.Task
  alias MemoizedModule
  require Logger;
  use Memoize

  def run(_) do
    MemoizedModule.get_value()
  end
end

defmodule MemoizedModule do
  use Memoize
  defmemo get_value() do
    1
  end
end

and it crashes with:它崩溃了:

/opt/app # mix my_task
** (ArgumentError) errors were found at the given arguments:

  * 1st argument: no persistent term stored with this key

    :persistent_term.get(:memoize_cache_strategy)
    (memoize 1.4.0) lib/memoize/config.ex:29: Memoize.Config.cache_strategy/0
    (memoize 1.4.0) lib/memoize/cache.ex:11: Memoize.Cache.tab/1
    (memoize 1.4.0) lib/memoize/cache.ex:103: Memoize.Cache.do_get_or_run/3
    (mix 1.12.3) lib/mix/task.ex:394: anonymous fn/3 in Mix.Task.run_task/3
    (mix 1.12.3) lib/mix/cli.ex:84: Mix.CLI.run_task/2
    (elixir 1.12.3) lib/code.ex:1261: Code.require_file/2

If I try to execute the code inside IEx, it works as expected:如果我尝试在 IEx 中执行代码,它会按预期工作:

/opt/app # iex -S mix
Interactive Elixir (1.12.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Mix.Tasks.MyTask.run()
1

I know it has something to do with some initialization that is not done in mix tasks, but I can´t figure out what it is.我知道这与混合任务中未完成的一些初始化有关,但我无法弄清楚它是什么。

We need to start applications explicitly in mix tasks.我们需要在混合任务中明确启动应用程序。

Codes are loaded, but applications are not started when running mix commands.代码已加载,但运行混合命令时应用程序未启动。

Mix does not automatically start our application or any of its dependencies... Ref Mix 不会自动启动我们的应用程序或其任何依赖项... Ref

So we need to start the it explicitly:所以我们需要明确地启动它:

def run(_) do
  {:ok, _} = Application.ensure_all_started(:memoize)

  MemoizedModule.get_value()
end

You may need to change :memoize to :my_otp_app if you have other initialization tasks in the app.如果您在应用程序中有其他初始化任务,您可能需要将:memoize更改为:my_otp_app

Why does it work inside iex -S mix ?为什么它在iex -S mix中起作用?

That's because iex -S mix [run] has started your application for you.那是因为iex -S mix [run]已经为您启动了您的应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM