问题描述
我是一些OTP概念的新手。我有GenServer,它将发布事件到RabbitMQ。此GenServer的状态为amqp Chanel
,该状态在init()期间启动一次,并且在cast
调用之间保持不变。
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
当我使用Myapp.Events.AmqpTransport.emit(%{"hop": "hej"})
调用它时,出现错误消息:
[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
我在这里错过了什么?
解决方法
您应该从GenDerver.handle_cast/2
返回两元素元组{:noreply,chan}
,而不是三元素元组{:noreply,:ok,chan}
。
投放是异步的,因此它们不会返回任何内容。您的三元素元组{:noreply,_,_}
被视为以下形式的响应
{:noreply,new_state,timeout() | :hibernate | {:continue,term()}}
和作为第三个元素传递的state
被认为是超时(它与:hibernate
或元组都不匹配),但是无论如何它的值都不是超时。