'mix edeliver start production' not starting. Issue with GenServer

I’m trying to deploy an application using edeliver and distillery. I’ve gone through the steps one by one and got till the end where I have to run ‘mix edeliver start production’ to start the application in the specified port. It says:

production node:

  user    : deploy
  host    : 172.105.49.38
  path    : /home/deploy/app_release
  response: 

START DONE!

But when I visit the site, it does not look like it has been deployed. So do things manually, I tried running the distillery command to check what was wrong like so:

_build/prod/rel/appname/bin/appname console

When I ran this command I got this:

13:03:18.758 [info] [alarm_handler: {:set, {:system_memory_high_watermark, []}}]
13:03:18.762 [info] Running MyAppWeb.Endpoint with cowboy 2.8.0 at :::5000 (http)
13:03:18.769 [info] Access MyAppWeb.Endpoint at http://172.105.49.38:5000
13:03:18.771 [info] Application scan_the_market exited: MyApp.Application.start(:normal, [:phoenix, :phoenix_eto, :myxql, :edeliver, :cowboy, :gettext, :phoenix_html, :phoenix_pubsub]) returned an error: shutdown: failed to start child: MyApp.Scheduler
    ** (EXIT) exited in: GenServer.call(Mix.State, {:get, {Map, :get, [:env, :dev]}}, :infinity)
        ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
[os_mon] memory supervisor port (memsup): Erlang has closed
13:03:18.779 [info] [alarm_handler: {:clear, :system_memory_high_watermark}]
[os_mon] cpu supervisor port (cpu_sup): Erlang has closed
{"Kernel pid terminated",application_controller,"{application_start_failure,scan_the_market,{{shutdown,{failed_to_start_child,'Elixir.MyApp.Scheduler',{noproc,{'Elixir.GenServer',call,['Elixir.Mix.State',{get,{'Elixir.Map',get,[env,dev]}},infinity]}}}},{'Elixir.MyApp.Application',start,[normal,[phoenix,phoenix_eto,myxql,edeliver,cowboy,gettext,phoenix_html,phoenix_pubsub]]}}}"}
Kernel pid terminated (application_controller) ({application_start_failure,scan_the_market,{{shutdown,{failed_to_start_child,'Elixir.MyApp.Scheduler',{noproc,{'Elixir.GenServer',call,['Elixir.

Crash dump is being written to: erl_crash.dump...done

MyApp.Scheduler is a genserver that runs scheduled tasks in the background, and I have included it in the supervsion tree at application.exs

So I figured it had something to do with the genserver being included as a child in the supervision tree. When I removed MyApp.Scheduler and went through the deployment flow, running the command mix edeliver start production started the application at the specified port.

Now if I include MyApp.Scheduler in the supervision tree and run MIX_ENV=prod PORT=5000 mix phx.server I seem to have no problem and the scheduler runs silently in the background without any issues.

This is how I have implemented MyApp.Scheduler:

defmodule MyApp.Scheduler do
  use GenServer
 
  @full_day 60 * 60 * 24 * 1000
  @ist_diff 19800000

  def start_link do
    GenServer.start_link(__MODULE__, %{}, name: CronJob)
  end

  def init(state) do
    scheduleJob()
    {:ok, state}
  end

  def perform_scheduled_tasks do
    #perform scheduled tasks
  end

  def handle_info({:update}, state) do
    perform_scheduled_tasks()
    scheduleJob()
    {:noreply, state}
  end

  defp scheduleJob() do
    update_home_loan_rates()
    {:ok, midnight} = Time.new(0, 0, 0)
    ms_past_midnight = abs(Time.diff(midnight, Time.add(Time.utc_now, @ist_diff, :millisecond), :millisecond))
    ms_until_midnight = @full_day - ms_past_midnight
    Process.send_after(self(), {:update}, ms_until_midnight)
  end
end

What am I doing wrong here?

My eyes are drawn to this part of the error

You’re trying to use Mix at runtime. Mix is not available in releases. Whatever conditional logic you have that is based on Mix.env should be read from the Application environment.

In my root.html.leex I’m doing a check like so:

<%= if Mix.env() == :prod do %>
<% end %>

To include some script tags only in the production environment. This is working as expected without the genserver worker included in the supervision tree.

I’m not understanding something here, why does Mix work for me in root.html.leex and not in the GenServer side of it

It is not working as expected.

Mix is only available during compilation. So if you start a release, its not there, unless you bundled it into the release (and we won’t tell you how to do this, as thats not the intended way to solve it`.

Instead of relying on Mix.env to show or hide portions of your views or to select code branches elsewhere, you should use configuration that makes semantically more sense.

<%= if Application.get_env(:my_app, :show_debug_interface) do %>
  <!-- Your debug interface here -->
<% end %>
1 Like

Thank you, that seemed to do the trick. Instead of using Mix.env I’ve set set the environment in the config file like so:

config :my_app, env: Mix.env

And now the env is being fetched else where like so

Application.get_env(:my_app, :env)

Even though this works, you really should use semantically meaningful names for the configs.

:enable_debug_interface is so much easier to understand for your future self than :env.

A nice side effect is, that semantic meaningful names enable you to enable/disable some of those meant-for-debugging-only features individually if you realize you need them in prod as well…

3 Likes