Tricote

Tricote

Recompilation triggered after request in dev even without code changes (iex -S mix phx.server)

Hi all,

I’m seeing some unexpected recompilation behavior in dev, and I’m not sure what’s causing it.

Here’s the flow:

  • rm -rf _build deps .elixir_ls
  • mix deps.get
  • mix clean and mix compile
  • I start my Phoenix app with MIX_DEBUG=1 iex -S mix phx.server.
  • Everything boots up cleanly (already compiled).
  • I haven’t modified any .ex files.
  • Then, as soon as I make a request in the browser, a recompilation is triggered:

Shortly after that, a background process (in my case, an Oban plugin) crashes with an UndefinedFunctionError, because the module it depends on (like MyApp.Repo) seems to have been purged and recompiled after app startup.

Here is the output from iex just after the browser request:

    iex()>
    -> Running mix compile.elixir --purge-consolidation-path-if-stale /home/xxxxxxxx/workspace/my_app/_build/dev/lib/my_app/consolidated --no-all-warnings (inside MyApp.MixProject)
    ...
    [error] GenServer {Oban.Registry, {Oban, Oban.Sonar}} terminating
** (UndefinedFunctionError) function MyApp.Repo.query/3 is undefined (module MyApp.Repo is not available
    # ... (more similar errors)
    [notice] Application oban_met exited: shutdown
    # .... (errors)
    Compiling 432 files (.ex)
    # .... (still errors)
    <- Ran mix compile.elixir in 18412ms
    -> Running mix compile.app --purge-consolidation-path-if-stale /home/xxxxxxxx/workspace/my_app/_build/dev/lib/my_app/consolidated --no-all-warnings (inside MyApp.MixProject)
    Generated my_app app
    <- Ran mix compile.app in 6ms
    -> Running mix compile.protocols (inside MyApp.MixProject)
    <- Ran mix compile.protocols in 32ms
    [info] GET /patient/patient_records/new
    # ...
    [notice] Application my_app exited: shutdown
    iex()>

Things I’ve already tried:

  • Disabled all watchers in config/dev.exs (same behaviour)
  • Verified that I’m not touching any files manually.
  • Confirmed that it only recompiles after an HTTP request, not on app boot.
  • If I disable CodeReloader, I don’t have the recompilation…
config :my_app, MyAppWeb.Endpoint,
  code_reloader: false

So it seems like Phoenix.CodeReloader is the one triggering the recompilation but why would Phoenix.CodeReloader trigger a recompilation if no source files changed?

I have also the standard config for live_reload Endpoint

# Watch static and templates for browser reloading.
config :my_app, MyAppWeb.Endpoint,
  live_reload: [
    patterns: [
      ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
      ~r"priv/gettext/.*(po)$",
      ~r"lib/my_app_web/(controllers|live|components)/.*(ex|heex)$"
    ]
  ]

Also note that this happened after an update to erlang 28.0.2, elixir 1.18.4 from elixir 1.17 / erlang 27.

Any insights appreciated!

Thanks :folded_hands:

Marked As Solved

Tricote

Tricote

Youhou I found the culprit!

I removed one by one each of my dependency, and it turns out that it was related to Kino. It was probably not a good idea to include it in my dev environment, but at the time I thought it was convenient in order to have Kino in attached livebooks…

So removing this line from my mix.exs file solved the issue:

 {:kino, "~> 0.16", only: :dev},

I don’t understand why exactly it breaks my env like this though…

Also Liked

axelson

axelson

Scenic Core Team

Ah, I think it’s related to this _mix_recompile__? definition within Kino. What is that assets_path pointing to in your environment?

https://github.com/livebook-dev/kino/blob/cb7dceb36caeee626707eebb738c78d1fbf9ff53/lib/kino/js.ex#L392

jonatanklosko

jonatanklosko

Creator of Livebook

I generated a new app with Phoenix 1.8.1, Kino 0.17.0, Elixir 1.19.0-rc.2 and Erlang 28.1. I don’t see any files recompiling during a request.

If someone has a minimal app where this happens with latest versions, I am happy to take a look.

Kino uses __mix_recompile__?, but it should definitely not return true without any changes (more specifically new modules using Kino.JS).

On a sidenote, I would generally recommend against depending on :kino in an app. When using Kino, instead of Attached mode, it’s best to use the default runtime and then execute code in the node using “Remote execution smart cell”, or just :erpc. This way the notebook can use arbitrary dependencies (Kino, all Kino* packages, and whatever else is needed).

Where Next?

Popular in Questions Top

stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 55125 245
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 44778 311
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement