You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用libcluster时,为何不执行mix clean就触发函数未定义错误?

Fixing Libcluster's Runtime Error on Second Run in an Umbrella Project

Hey there, let's break down this issue you're facing—first mix run works fine, but the second time around libcluster throws a runtime error when trying to call your custom connect function. I've run into similar quirks with umbrella projects and libcluster, so here's what's likely going on and how to fix it:

What's Causing This?

The root problem almost always ties to module loading timing in umbrella projects or Mix's hot-reload behavior. On a cold first run, all your modules get loaded properly. But when you run mix run again, Mix might skip reloading certain modules, or libcluster might be using cached configuration that references a module that's not properly loaded anymore.

Step-by-Step Fixes

1. Force Your Subapp to Load Before Libcluster

Umbrella apps have a startup order, and if your custom Module.Name lives in a subapp that loads after libcluster, the second run can fail because libcluster tries to access the module before it's ready.

  • In your root mix.exs, update the included_applications list to put your subapp first:
    def application do
      [
        mod: {MyUmbrellaRoot.Application, []},
        extra_applications: [:logger],
        included_applications: [:your_sub_app, :libcluster] # Your subapp first!
      ]
    end
    
  • Alternatively, add libcluster as a dependency in your subapp's mix.exs—this ensures your subapp loads before libcluster:
    defp deps do
      [
        {:libcluster, "~> 3.0"}
      ]
    end
    

2. Use Runtime Configuration Instead of Static Config

Hardcoding the module reference in dev.exs can cause issues because config files load early, before all modules are available. Instead, set the config dynamically when your app starts:

# In your subapp's application.ex (or root umbrella app's application.ex)
def start(_type, _args) do
  # Make sure your module is loaded before setting the config
  Code.ensure_loaded?(Module.Name)

  # Dynamically set libcluster's connect config
  Application.put_env(:libcluster, :connect, {Module.Name, :function, args})

  # Start your supervisor tree as usual
  children = [
    # Your existing children...
    {Cluster.Supervisor, [Application.get_env(:libcluster, :topologies), [name: MyApp.ClusterSupervisor]]}
  ]

  Supervisor.start_link(children, strategy: :one_for_one)
end

3. Disable Hot-Reload (For Testing)

If you suspect hot-reload is the culprit, run Mix without reload to test:

mix run --no-halt --no-reload

If this fixes the second run, you can tweak which apps get reloaded in dev.exs:

config :mix, reloadable_apps: [:your_sub_app] # Only reload your subapp, not libcluster

4. Double-Check Your Module Definition

It sounds obvious, but make sure your module name matches exactly what's in your config. If your config says {Module.Name, :function, args}, your lib/module/name.ex should start with:

defmodule Module.Name do
  def function(arg) do
    # Your logic here
  end
end

Also confirm the subapp containing this module is listed in your umbrella's mix.exs under apps: [:your_sub_app, ...].

How to Verify

After making changes, clear Mix's cache first to rule out old configs:

mix clean && mix run --no-halt

Run this once, then run mix run --no-halt again—if the error is gone, you're good to go!

内容的提问来源于stack exchange,提问作者philosodad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:23:38