Reputation: 11251
I am new to some OTP concepts. I have GenServer, that will Publish events to RabbitMQ. This GenServer has the state: amqp Chanel
which is initiates once during init() and is persistent between cast
invokes.
defmodule Myapp.Events.AmqpTransport do
require Logger
use GenServer
use AMQP
def start_link(_) do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end
def init(_opts) do
username = get_conf(:username)
password = get_conf(:password)
host = get_conf(:host)
port = get_conf(:port)
vhost = String.replace(get_conf(:vhost), "/", "%2f")
exchange = get_conf(:exchange)
{:ok, conn} = Connection.open("amqp://#{username}:#{password}@#{host}:#{port}/#{vhost}")
{:ok, chan} = Channel.open(conn)
{:ok, chan}
end
def handle_cast({:emit, event}, chan) do
payload = :jiffy.encode(%{event: event})
Basic.publish(
chan,
get_conf(:exchange),
get_conf(:routing_key),
payload
)
{:noreply, :ok, chan}
end
def emit(event) do
GenServer.cast(__MODULE__, {:emit, event})
end
defp get_conf(key) do
conf = Application.get_env(:myapp_events, :rabbit)
conf[key]
end
end
When I call it using Myapp.Events.AmqpTransport.emit(%{"hop": "hej"})
I get error:
[error] Supervisor 'Elixir.Myapp.Events.Supervisor' had child
'Elixir.Myapp.Events.AmqpTransport' started with
'Elixir.Myapp.Events.AmqpTransport':start_link([])
at <0.7024.0> exit with reason timeout_value
in gen_server:loop/7 line 437
in context child_terminated
What I missed here?
Upvotes: 3
Views: 267
Reputation: 120990
You should return two-element tuple {:noreply, chan}
, not three-element tuple {:noreply, :ok, chan}
from GenDerver.handle_cast/2
.
Casts are async and hence they don’t return anything. Your three-element tuple {:noreply, _, _}
is treated as a response in a form
{:noreply, new_state,
timeout() | :hibernate | {:continue, term()}}
and the state
, passed as a third element, is expected to be a timeout (it does not match :hibernate
, nor the tuple), but its value is not a timeout by any means.
Upvotes: 3