elixir-maru / maru

Elixir RESTful Framework
https://maru.readme.io
BSD 3-Clause "New" or "Revised" License
1.32k stars 84 forks source link

Error while deploying to Heroku #74

Open lucaskalves opened 7 years ago

lucaskalves commented 7 years ago

I have an issue to deploy a simple application to Heroku. Heroku always responds with the following error:

2017-08-18T18:36:18.054272+00:00 heroku[web.1]: Starting process with command `mix run --no-halt`
2017-08-18T18:36:22.356225+00:00 app[web.1]:
2017-08-18T18:36:22.356245+00:00 app[web.1]: 18:36:22.351 [info]  Starting Elixir.JesseAPI with Cowboy on http://127.0.0.1:59996
2017-08-18T18:37:18.586685+00:00 heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
2017-08-18T18:37:18.586685+00:00 heroku[web.1]: Stopping process with SIGKILL
2017-08-18T18:37:18.695398+00:00 heroku[web.1]: Process exited with status 137

Here is my config.exs (using {:system, "PORT"} was causing other issues):

use Mix.Config

config :maru, JesseAPI,
    http: [port: System.get_env("PORT")]

And here is my elixir_buildpack.config:

# Erlang version
erlang_version=20.0

# Elixir version
elixir_version=1.5.0

# Always rebuild from scratch on every deploy?
always_rebuild=true

Does anyone have any clue of what may be going on?

falood commented 7 years ago

Can you try to add confex as a depend and use {:system, "PORT"} in the config?

lucaskalves commented 7 years ago

With Confex I get a similar error to when I was using {:system, "PORT"} in the first place:

2017-08-19T16:45:45.234872+00:00 heroku[web.1]: State changed from crashed to starting
2017-08-19T16:45:48.760783+00:00 heroku[web.1]: Starting process with command `mix run --no-halt`
2017-08-19T16:45:53.362469+00:00 app[web.1]: {"Kernel pid terminated",application_controller,"{application_start_failure,maru,{{undef,[{'Elixir.Confex',process_env,[[{http,[{port,{system,<<\"PORT\">>}}]}]],[]},{'Elixir.Maru.Supervisor','-maru_servers/0-fun-0-',1,[{file,\"lib/maru/supervisor.ex\"},{line,55}]},{'Elixir.Enum','-map/2-lists^map/1-0-',2,[{file,\"lib/enum.ex\"},{line,1255}]},{'Elixir.Maru.Supervisor',init,1,[{file,\"lib/maru/supervisor.ex\"},{line,15}]},{supervisor,init,1,[{file,\"supervisor.erl\"},{line,294}]},{gen_server,init_it,2,[{file,\"gen_server.erl\"},{line,365}]},{gen_server,init_it,6,[{file,\"gen_server.erl\"},{line,333}]},{proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,247}]}]},{'Elixir.Maru',start,[normal,[]]}}}"}
2017-08-19T16:45:53.362667+00:00 app[web.1]: Kernel pid terminated (application_controller) ({application_start_failure,maru,{{undef,[{'Elixir.Confex',process_env,[[{http,[{port,{system,<<"PORT">>}}]}]],[]},{'Elixir.Maru.Supervisor','-maru_serve

When I try to execute locally, I get this message:

Generated jesse_api app

=INFO REPORT==== 19-Aug-2017::14:44:38 ===
    application: logger
    exited: stopped
    type: temporary
** (Mix) Could not start application maru: Maru.start(:normal, []) returned an error: an exception was raised:
    ** (UndefinedFunctionError) function Confex.process_env/1 is undefined or private
        (confex) Confex.process_env([http: [port: {:system, "PORT"}]])
        (maru) lib/maru/supervisor.ex:55: anonymous fn/1 in Maru.Supervisor.maru_servers/0
        (elixir) lib/enum.ex:1255: Enum."-map/2-lists^map/1-0-"/2
        (maru) lib/maru/supervisor.ex:15: Maru.Supervisor.init/1
        (stdlib) supervisor.erl:294: :supervisor.init/1
        (stdlib) gen_server.erl:365: :gen_server.init_it/2
        (stdlib) gen_server.erl:333: :gen_server.init_it/6
        (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

Here is my mix.exs file:

defmodule JesseAPI.Mixfile do
  use Mix.Project

  def project do
    [
      app: :jesse_api,
      version: "0.1.0",
      elixir: "~> 1.5",
      start_permanent: Mix.env == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      {:maru, "~> 0.12"},
      {:confex, "~> 3.2.3"}
    ]
  end
end
falood commented 7 years ago

I just checked, the confex API changed. will release a new version for the latest version of confex

falood commented 7 years ago

fixed and released v0.12.3, Thank you!

jalcine commented 7 years ago

Will it possible in the future to not have to include confex as a parent dependency for projects?

falood commented 7 years ago

@jalcine For now, all maru services started by Application.start(:maru), it's bad. I'll make something like Maru.child_spec(module, options) to make it a supervisor child and developers can put it in any supervisor tree they want πŸ™‚ and then, the options can be totally custom and confex is nolonger a dependency.

Thank you for the suggestion

jalcine commented 7 years ago

Oh okay! I'm a bit new to this scene - do you have an example of how this would work? This would be helpful in the README about setting up an application.

On Thursday, September 7, 2017 7:13:47 PM PDT Xiangrong Hao wrote:

@jalcine For now, all maru services started by Application.start(:maru), it's bad. I'll make something like Maru.child_spec(module, options) to make it a supervisor child and developers can put it in any supervisor tree they want πŸ™‚ and then, the options can be totally custom and confex is nolonger a dependency.

Thank you for the suggestion

falood commented 7 years ago

we don't have this for now 😞 I'm still working on refactor the code, will let you know when finished.

KamilLelonek commented 6 years ago

Hey, it seems the problem still exists, right?

falood commented 6 years ago

@KamilLelonek

Oh, this feature is already released with 0.13.2, confex is not a dependent of maru any more, but you can use it in your own project.

follow such steps to start maru in your own supervisor tree:

  1. Add a new module in your project:
defmodule MyAPP.Server do
  use Maru.Server, otp_app: :my_app

  def init(_type, opts) do
    Confex.Resolver.resolve(config)
  end
end
  1. and modify the config file like this:
config :my_app, MyAPP.Server,
  adapter: Plug.Adapters.Cowboy2,
  plug: MyAPP.API,
  scheme: :http,
  port: {:system, "PORT"}

config :my_app,
  maru_servers: [MyAPP.Server]
  1. replace use Maru.Router to use MyAPP.Server.

  2. add MyAPP.Server to the children of your supervisor tree.

I'm not sure whether it's clear enough, feel free to let me know if you get other issues.

mrusme commented 5 years ago

I looked for an hour on how to solve this issue until I found this. However, the code seems to be not quite right, hence here's what I went with:

     def init(_type, opts) do
        Confex.Resolver.resolve(opts)
    end

Maybe this should be documented somewhere?

falood commented 5 years ago

@mrusme sorry for that, will do πŸ™ˆ