beerlington

beerlington

Heroku app recompiles after restarts using Elixir 1.15

I upgraded to Elixir 1.15 and am having issues deploying on Heroku now. Whenever the app restarts, the whole application recompiles. On our large application, this recompile takes longer than 30 seconds, which causes the app to crash.

I’m able to reproduce this on a bare bones Phoenix app. The line where it says “Compiling 15 files” should not be happening during a restart.

2023-07-06T14:42:59.587968+00:00 heroku[web.1]: Restarting
2023-07-06T14:42:59.650735+00:00 heroku[web.1]: State changed from up to starting
2023-07-06T14:43:00.295043+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2023-07-06T14:43:00.322078+00:00 app[web.1]: 14:43:00.321 [notice] SIGTERM received - shutting down
2023-07-06T14:43:00.322086+00:00 app[web.1]: 
2023-07-06T14:43:01.502645+00:00 heroku[web.1]: Process exited with status 0
2023-07-06T14:43:03.720077+00:00 heroku[web.1]: Starting process with command `mix phx.server`
2023-07-06T14:43:05.363804+00:00 app[web.1]: Compiling 15 files (.ex)

Where should I report this issue? I don’t know if it’s something specific to Elixir or if the Heroku buildpack we’re using needs to be updated to support Elixir 1.15. GitHub - HashNuke/heroku-buildpack-elixir: Heroku Buildpack for Elixir with nitro boost · GitHub

Marked As Solved

johantell

johantell

Yes, running the migrations through mix will force recompilation. There is a way around it though, i think its described quite well under the phoenix release docs. In short its a helper function that is called via the release through the eval command

Also Liked

AlfredBaudisch

AlfredBaudisch

For those coming here with a setup similar to mine:

  • Elixir 1.15
  • OTP 26
  • Heroku
  • Phoenix 1.7
  • And Umbrella app (4 apps)

The solution to make it work with Heroku, as explained previously, is to migrate to use Releases, but then, Node and npm weren’t being run so statics assets were not being compiled (i.e. apps/xxx/assets).

In the end I made it work in Heroku by adding a Procfile manually, keeping the Elixir and Phoenix static assets buildpacks, adding an additional “elixir mix release” buildpack and setting Phoenix Endpoint as a server.

Configuration step by step:

Phoenix Endpoint

I had a lot of trouble making Phoenix start in Heroku when building the mix release. In the end, this is what I needed to put inside config/runtime.exs. The secret lies in adding server: true, otherwise the Elixir release won’t start Phoenix as a server and Heroku will timeout on startup.

if config_env() == :prod do
  config :fb_web, Farmbackup.Endpoint,
    http: [
      port: {:system, "PORT"},
      compress: true,
      timeout: 60_000,
      protocol_options: [
        idle_timeout: 60_000
      ]
    ],
    url: [scheme: "https", host: System.fetch_env!("FARMBACKUP_HOST"), port: 443],
    debug_errors: false,
    cache_static_manifest: "priv/static/cache_manifest.json",
    secret_key_base: System.fetch_env!("SECRET_KEY_BASE"),
    server: true
end

mix.exs release

In the main mix.exs file add all your umbrella apps in the releases config key:

  def project do
    [
      apps_path: "apps",
      start_permanent: Mix.env() == :prod,
      deps: deps(),
      aliases: aliases(),
      releases: [
        fb_task: [
          applications: [
            fb_web: :permanent,
            fb_db: :permanent,
            fb_invoice: :permanent,
            fb_salary: :permanent
          ],
          version: DateTime.utc_now() |> DateTime.to_iso8601()
        ]
      ]
    ]
  end

Heroku Buildpacks

You are going to need these 3 buildpacks installed in order:

https://github.com/HashNuke/heroku-buildpack-elixir.git
https://github.com/gigalixir/gigalixir-buildpack-phoenix-static
https://github.com/chrismcg/heroku-buildpack-elixir-mix-release

Buildpack config

elixir_buildpack.config

erlang_version=26.1.2
elixir_version=1.15.7
always_rebuild=false
runtime_path=/app

phoenix_static_buildpack.config

clean_cache=true
phoenix_relative_path=apps/fb_web (i.e. app in the umbrella which has `/assets`)
assets_path=apps/fb_web/assets
node_version=v14.15.5
npm_version=6.14.11

Procfile

YOU need to manually create a Heroku Procfile for Umbrellas.

In our case it is:

web: _build/prod/rel/fb_task/bin/fb_task start
iamyojimbo

iamyojimbo

I have posted an update here: Additional recompile occurring on Heroku with Elixir 1.15 causing boot issues · Issue #12771 · elixir-lang/elixir · GitHub

Read there for more detail. The root cause is that elixir 1.15 introduced cwd in the cache key after compilation. Heroku compiles code in a tmp build dir, but is run from /app.

Fix it by using your exact same Procfile as before, but passing in --no-compile, as detailed here: Changing absolute path of mix project causes full recompilation · Issue #13241 · elixir-lang/elixir · GitHub

So change your procfile to:

release: mix do ecto.migrate --no-compile, any_other_example_mix_command
web: MIX_ENV=prod mix phx.server --no-compile

You do not need to use releases.

Where Next?

Popular in Questions Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
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
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
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
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
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
earth10
Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone. What strikes me is th...
New

Other popular topics Top

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
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
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
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
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
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement