Erlang 未调用Elixir GenServer句柄\u强制转换
我有一个问题与处理铸造。模块加载后,会调用定期通信,每5秒调用一次保存数据方法。在我的save_data方法中,正在打印日志,但语句不执行任何操作Erlang 未调用Elixir GenServer句柄\u强制转换,erlang,elixir,gen-server,nerves-project,Erlang,Elixir,Gen Server,Nerves Project,我有一个问题与处理铸造。模块加载后,会调用定期通信,每5秒调用一次保存数据方法。在我的save_data方法中,正在打印日志,但语句不执行任何操作 GenServer.cast(__MODULE__, {:save_load_data, data}) 这里定义了句柄转换方法 def handle_cast({:save_load_data, data}, state) do Logger.error("uin saving data=======================
GenServer.cast(__MODULE__, {:save_load_data, data})
这里定义了句柄转换方法
def handle_cast({:save_load_data, data}, state) do
Logger.error("uin saving data====================================")
# state = Map.put_new(state, :load_data, data)
# Logger.debug "updated state : #{inspect state}"
{:noreply, state}
end
整个文件如下所示
defmodule Core.Inverter.Manager do
# core inverter process that handles the inverter communication
use GenServer
require Logger
def start_link(_) do
Logger.info("putting some string")
GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
end
@impl true
def init(_) do
Logger.info("inverter Manager init'ed")
{:ok, %{configs: nil, inverter_connection: nil, inverter_impl: nil}}
end
# public api
# initialize the inverter and start periodic comm
def init_inverter(configs) do
GenServer.cast(__MODULE__, {:init_inverter, configs})
GenServer.cast(__MODULE__, {:start_periodic_comm, configs})
end
def inverter_off() do
GenServer.call(__MODULE__, :inverter_off)
end
@impl true
def handle_cast({:init_inverter, configs}, state) do
Logger.debug("initializing the inverter")
# fetching inverter type/configurations
inverter_impl = get_inverter_impl(configs)
# initializing inverter comm channel
inverter_connection = inverter_impl.init(configs)
state = %{
configs: configs,
inverter_connection: inverter_connection,
inverter_impl: inverter_impl
}
Logger.warn("inverter type #{state.inverter_impl}")
{:noreply, state}
end
def handle_cast({:start_periodic_comm, configs}, state) do
Logger.warn(
"Actually Starting inverter periodic COMM with inverter type #{state.inverter_impl}"
)
start_periodic_comm(state)
{:noreply, state}
end
@impl true
def handle_call(
:inverter_off,
_from,
%{inverter_impl: inverter_impl, inverter_connection: inverter_connection} = state
) do
{:ok, inverter_connection} = inverter_impl.inverter_off(inverter_connection)
{:reply, :ok, %{state | inverter_connection: inverter_connection}}
end
def handle_cast({:save_load_data, data}, state) do
Logger.error("uin saving data====================================")
# state = Map.put_new(state, :load_data, data)
# Logger.debug "updated state : #{inspect state}"
{:noreply, state}
end
defp start_periodic_comm(state) do
periodic_comm(state)
end
defp periodic_comm(state) do
# call functions from the inverter_type module, e.g infit.ex
receive do
after
5000 ->
{:ok, data} = state.inverter_impl.get_load_data(state)
save_data(data)
end
periodic_comm(state)
end
# defp save_data() do end
def save_data(data) do
Logger.debug("saving data")
Logger.debug("in savinf data data is : #{inspect(data)}")
GenServer.cast(__MODULE__, {:save_load_data, data})
end
defp get_inverter_impl(configs) do
# add case statements here
Core.Inverter.Infini
end
end
我对elixir的语法不太熟悉,但在我看来,周期通信是循环的:
defp periodic_comm(state) do
# call functions from the inverter_type module, e.g infit.ex
receive do
after
5000 ->
{:ok, data} = state.inverter_impl.get_load_data(state)
save_data(data)
end
periodic_comm(state)
end
不管save_data的结果如何,线程都会无休止地循环调用周期性_comm,因此它没有机会接收和执行save_load_data消息
为了修复它,您应该重构服务器,使其具有handle_X中的逻辑,而不存在接收各种消息的循环。您可以使用erlang:start\u timer我不知道elixir的对应项,或者依赖gen\u服务器返回值中的超时来接收超时消息。我对elixir的语法不太熟悉,但在我看来,周期性通信是循环的:
defp periodic_comm(state) do
# call functions from the inverter_type module, e.g infit.ex
receive do
after
5000 ->
{:ok, data} = state.inverter_impl.get_load_data(state)
save_data(data)
end
periodic_comm(state)
end
不管save_data的结果如何,线程都会无休止地循环调用周期性_comm,因此它没有机会接收和执行save_load_data消息
为了修复它,您应该重构服务器,使其具有handle_X中的逻辑,而不存在接收各种消息的循环。您可以使用erlang:start_timer我不知道长生不老药的对应物,或者依赖gen_服务器返回值中的超时来接收超时消息。我会使用:timer.send_interval发送这样的重复消息。@PawełObrok如果计时器数量很大,计时器模块的伸缩性很差,有时这可能是个问题。erlang:start_timer以一种更具可扩展性的方式在内部处理计时器。我会检查一下,然后在this@Jos嗯,这是一个很好的观点,但当然取决于你的使用情况。文档中说,如果许多进程频繁地创建和取消计时器-如果您在系统启动时创建了固定数量的计时器,这些计时器每隔几分钟或其他时间触发一次,这可能不是问题。@PawełObrok这是我们的使用案例计时器将在启动时创建,并在不同模块上以固定频率启动。我会使用:timer.send_interval发送这样的重复消息。@PawełObrok如果计时器数量巨大,计时器模块的伸缩性很差,有时这可能是个问题。erlang:start_timer以一种更具可扩展性的方式在内部处理计时器。我会检查一下,然后在this@Jos嗯,这是一个很好的观点,但当然取决于你的使用情况。文档中说,如果许多进程频繁地创建和取消计时器-如果您在系统启动时创建了固定数量的计时器,并且每隔几分钟或其他时间触发一次,这可能不是问题。@PawełObrok这是我们的使用案例,计时器将在启动时创建,并在不同模块上以固定频率触发。