Reputation: 4588
I have a working GenServer and working Supervisor. If I launch the Supervisor the GenServer is launched. If the GenServer is killed the Supervisor restarts it.
I am now trying to launch my code as an "Application". To do this I am changing code in my mix.exs file.
My entire code is below. The error I asm getting is at the very bottom
todos/lib/todos.exs
defmodule App.Service do
use GenServer
def start_link(state) do
GenServer.start_link(__MODULE__, state, name: __MODULE__)
end
def init(state) do
{:ok, state}
end
def get_state(pid) do
GenServer.call(pid, :get_state)
end
def set_state(pid,state) do
GenServer.call(pid, {:set_state, state})
end
def handle_call(:get_state, _from, state) do
{:reply, state, state}
end
def handle_call({:set_state, new_state}, _from, state)do
{:reply,state,[new_state | state]}
end
end
defmodule App.Supervisor do
use Supervisor
def start do
Supervisor.start_link(__MODULE__, [])
end
def init(_) do
children = [
{App.Service,[]}
]
Supervisor.init(children, strategy: :one_for_one)
end
end
todos/mix.exs
defmodule Todos.MixProject do
use Mix.Project
def project do
[
app: :todos,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
extra_applications: [:logger],
mod: {App, []} # this is the only line I changed
]
end
defp deps do
[
]
end
end
Error
[notice] Application todos exited: exited in: App.start(:normal, [])
** (EXIT) an exception was raised:
** (UndefinedFunctionError) function App.start/2 is undefined (module App is not available)
App.start(:normal, [])
(kernel 8.5) application_master.erl:293: :application_master.start_it_old/4
** (Mix) Could not start application todos: exited in: App.start(:normal, [])
** (EXIT) an exception was raised:
** (UndefinedFunctionError) function App.start/2 is undefined (module App is not available)
App.start(:normal, [])
(kernel 8.5) application_master.erl:293: :application_master.start_it_old/4
I am unsure what the App.start() method error is referring to, or how to fix this problem.
Upvotes: 0
Views: 580
Reputation: 9638
Your mix.exs
would need to reference a module that uses the Application
module -- the convention is that this is the lib/your_app/application.ex
, but that's just a convention. The referenced module just needs to have use Application
. This is something like how the main
function gets called in languages like Go
or Rust
, it's the entry point for the thing when it's running as an app.
Side note: I know this is an example for Stack Overflow, but do not name your applications using a generic name like App
. That's a common convention in some languages/frameworks (e.g. PHP), but in Elixir, it's possible that you have multiple applications running in the same BEAM simultaneously, and they must each have unique names.
So the correct way to fix your code is to:
Application
. (It's similar to a supervisor, but it's like THE supervisor). The Application is what would start your GenServer and anything else your app needs to run.defmodule Todos.Application do
@moduledoc false
use Application
@impl true
def start(_type, _args) do
children = [
{App.Service, []},
]
opts = [strategy: :one_for_one, name: Todos.Supervisor]
Supervisor.start_link(children, opts)
end
end
mix.exs
to reference the Todos.Application
module: def application do
[
extra_applications: [:logger],
mod: {Todos.Application, []}
]
end
Upvotes: 3