marick

marick

How does `Phoenix.CodeReloader ` work? (I'm trying to do something simpler)

The description for Phoenix.CodeReloader starts like this:

For each request, Phoenix goes through all modules and checks if any of them implement a __phoenix_recompile__?/0 function. If they do and it returns true, the module source file is touched, forcing it to be recompiled. For this functionality to work, Phoenix requires you to add the :phoenix compiler to your list of compilers: […]

Can someone explain how this works? I’m confused by:

  • Where does __phoenix_recompile__? come from?
  • What does adding :phoenix to the list of compilers do?
  • Where does the reloading of a successfully-compiled new version of a source file happen?

What I want to accomplish

To learn LiveView, I want to provide a localhost view into the runtime structure created by a set of modules. The modules have very specific constraints that mean I don’t need to care about a lot of special cases. What I have is:

  • a set of modules. Each has a single “constructor” function (all with the same name) that makes a big nested structure.
  • a genserver module that maintains a map from module name to big nested structure.

My “watcher” app is to start by loading up all the modules, populating the genserver map, and displaying pretty things in a browser interface.

When one of the module source files is (successfully) changed, I want the watcher app to:

  1. Notice that a module is out of date (probably via file_system).
  2. Delete that module from the genserver.
  3. Load the new version of the module’s code.
  4. Run the constructor function and add the new big nested structure to the genserver.

By “very specific constraints” above, I mean, for example, that there are no compile-time dependencies between these modules. There’s an extra level of indirection meaning that the Animal module does not have to be redefined when the Species module changes.

Because my case is so simple, it seems like Phoenix.CodeReloader, phoenix_live_reload, the vsn module attribute, and IEX’s r command are doing things I don’t have to do.

I’m hoping I don’t have to understand complicated cases to implement the simple case.

Marked As Solved

axelson

axelson

Scenic Core Team

Sounds like an interesting visualization! I’m excited to hear more about it eventually.

I think you might be interested in looking at exsync which is an alternative code reloader that is built on file_system (and that I help maintain):
https://github.com/falood/exsync/

The code should be pretty easy to follow and it’s easy to change the code to call a function every time a module is changed.

Also Liked

marick

marick

Thank you all. exsync is easy to understand. The trick I was missing was that Code doesn’t reveal the two functions :code.load_file and :code.load_binary. You can see how the latter is used in exsync here.

@josevalim: Would it be useful to add something like the following text at the end of the Working with files section of the Code documentation?

“The three functions above work with Elixir source. If you want to load a compiled file (typically found below the _build directory of a Mix project, with the extension .beam), see the Erlang functions :code.load_file/1 and :code.load_binary/3.”

That would have saved me from taking some unproductive paths. If so, I’ll make a PR.

josevalim

josevalim

Creator of Elixir

Yeah, a PR is welcome!

josevalim

josevalim

Creator of Elixir

FWIW, Phoenix.CodeReloader calls mix compile under the hood. It is not effectively compiling. The custom compiler and __phoenix_recompile__? were specific for template reloading but this feature has been moved to Mix and will be deprecated from Phoenix.

From your description, you probably want to play with the Code module in Elixir and the associated :code module in Erlang - as it seems you don’t want to compile the code but act on the code that is available/has been compiled.

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
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
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
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