标签: gen-server

如何在erlang中测试gen服务器?

我是erlang的初学者,我写了一个基本的gen服务器程序如下,我想知道,如何测试服务器让我知道它运行良好.

-module(gen_server_test).
-behaviour(gen_server).
-export([start_link/0]).
-export([alloc/0, free/1]).
-export([init/1, handle_call/3, handle_cast/2]).
start_link() ->
    gen_server:start_link({local, gen_server_test}, ch3, [], []).
alloc() ->
    gen_server:call(gen_server_test, alloc).
free(Ch) ->
    gen_server:cast(gen_server_test, {free, Ch}).
init(_Args) ->
    {ok, channels()}.
handle_call(alloc, _From, Chs) ->
    {Ch, Chs2} = alloc(Chs),
    {reply, Ch, Chs2}.
handle_cast({free, Ch}, Chs) ->
    io:format(Ch),
        io:format(Chs),
        Chs2 = free(),
    {noreply, Chs2}.

free() -> 
        io:format("free").
channels() ->
        io:format("channels").
alloc(chs) -> 
        io:format("alloc chs").
Run Code Online (Sandbox Code Playgroud)

BTW:该程序可以编译,它不是一个好程序,我只想打印一些东西,以确保它的工作:)

erlang gen-server

3
推荐指数
1
解决办法
1480
查看次数

otp gen_server的info,call,cast message queue中有不同的优先级吗?

在编写代码时,我会问自己应该使用call哪种类型的消息,应该使用哪种类型的消息info

在这个问题下面,还有另一个长期怀疑info, cast, call消息之间是否存在优先级差异?这3种消息是否共享同一队列?

erlang message-queue gen-server

3
推荐指数
1
解决办法
796
查看次数

gen_server中的错误也会终止调用进程?

我的gen_server包含这样的方法:

handle_call(error, From, State) ->
    io:format("Inside the handle_call error~n"),
    1/0.
Run Code Online (Sandbox Code Playgroud)

它提供start(非start_link)功能:

start() ->
    gen_server:start({local, ?MODULE}, ?MODULE, [], []).

normal_call() ->
    gen_server:call(?MODULE, {normal}).

error_call() ->
    gen_server:call(?MODULE, error).
Run Code Online (Sandbox Code Playgroud)

start从shell 调用函数:

c(some_module).
some_module:start().
Run Code Online (Sandbox Code Playgroud)

然后我调用终止服务器进程的错误调用,因为除零错误,但它也终止了shell(调用进程).我不明白为什么?它们没有链接但仍然使用新的pid重新启动shell.这是gen_server的预期行为,还是我做错了什么?

更新:它仍然无法正常工作,以帮助我发布完整的代码.

-module(some_test).
-behaviour(gen_server).
-compile(export_all).

%% api functions, can be directly used by the user

start() ->
    gen_server:start({local, ?MODULE}, ?MODULE, [], []).

normal_call() ->
    gen_server:call(?MODULE, normal, infinity).

error_call() ->
    gen_server:call(?MODULE, error, infinity).

%% service specific function shoule not be call directly

init(_) ->
    io:format("Inside …
Run Code Online (Sandbox Code Playgroud)

erlang erlang-otp gen-server erlang-shell

3
推荐指数
1
解决办法
1164
查看次数

瞬态gen_server处理和更新pids

我目前正在以合理的方式学习Erlang,但对主管的gen_server有疑问.如果gen_server进程崩溃并由主管重新启动,它将收到一个新的pid.现在,如果我希望其他进程通过Pid引用该进程,该怎么办?在这些流程中"更新"Pid有哪些好的惯用方法?

作为一个实际应用的练习,我正在编写一个锁定服务器,客户端可以使用任意键请求锁定.理想情况下,我希望有一个单独的进程来处理特定锁的锁定和释放,这个想法是我可以使用gen_server中的timeout参数来终止进程,如果在N个时间之后没有人请求它,那么只有当前相关的锁将留在内存中.现在,我有一个目录进程,它将锁名称映射到锁进程.当锁定进程终止时,它会从目录中删除锁定.

我关心的是如何处理客户端在锁定进程正在终止时请求锁定的情况.它还没有关闭,所以嗅到pid活着是行不通的.锁定进程尚未到达从目录中删除它的子句.

有没有更好的方法来处理这个?

编辑

目前有两个gen_servers:'directory'维护一个来自LockName - > Lock Process的ETS表,以及'lock servers',它们使用start_child动态添加到监督树.理想情况下,我希望每个锁服务器直接处理与客户端的通话,但我担心当进程处于崩溃中时,获取/释放获取/释放请求的场景(因此将不会响应)消息).

从{local}或{global}开始将无效,因为可能有N个.

erlang multithreading gen-server

2
推荐指数
1
解决办法
403
查看次数

如果在handle_call函数中有"record = State"会发生什么?

gen_server中的handle_call函数是:

Module:handle_call(Request, From, State) -> Result
Run Code Online (Sandbox Code Playgroud)

但是我遇到了一个这样的handle_call函数:

handle_call(info, _From, #yuv{decoder = undefined} = State) ->
  {reply, [], State};

handle_call(info, _From, #yuv{decoder = Decoder} = State) ->
  {reply, av_decoder:info(Decoder), State};

handle_call(_Request, _From, State) ->
  {noreply, ok, State}.
Run Code Online (Sandbox Code Playgroud)

我想知道发生了什么?它超越了我的头脑

BTW:yuv记录是:

-record(yuv, {
  host,
  name,
  media,
  decoder,
  consumer
}).
Run Code Online (Sandbox Code Playgroud)

erlang gen-server

2
推荐指数
1
解决办法
221
查看次数

如何制作以特定速率处理消息的 GenServer?(每 n 秒)

我的一项服务与速率受限的外部 API 通信,因此我想确保每 10 秒发送不超过 1 个调用。

我天真的方法是拥有一个长时间运行的 API 服务,并在每次调用后超时:

def handle_cast({:call_api, data}, state) do
  send_to_external_api(data)
  :timer.sleep(10000)
  {:noreply, state}
end
Run Code Online (Sandbox Code Playgroud)

我不确定是否有适当的方法来做到这一点。

elixir gen-server

2
推荐指数
1
解决办法
1251
查看次数

为什么单词"cast"用于处理GenServer中的异步消息?

为什么,在Erlang/Elixir中,是以?GenServer命名的异步处理程序handle_cast?该handle_部分是显而易见的,但为什么这个词

我能想到的唯一的事情是,它是类似于刚才扔的东西在那里(如在荷兰国际集团的净)与呼叫荷兰国际集团出来的东西,等待答复.

erlang elixir erlang-otp gen-server

2
推荐指数
1
解决办法
88
查看次数

GenServer.call 产生“无进程”错误

我有一个使用 ETS 的原始缓存的 GenServer/客户端实现:

defmodule Cache do
    use GenServer

    def start_link() do
        GenServer.start_link(__MODULE__, [])
    end

    def fetch(key, def_value) do
        case get(key) do
            {:not_found} -> set(key, def_value)
            {:found, result} -> result
        end
    end

    defp get(key) do
        case GenServer.call(__MODULE__, {:get, key}) do
            [] -> {:not_found}
            [{_, result}] -> {:found, result}
        end
    end

    defp set(key, value) do
        GenServer.call(__MODULE__, {:set, key, value})
    end

    # GenServer callbacks

    def handle_call({:get, key}, _from, state) do
        result = :ets.lookup(:my_table, key)
        {:reply, result, state}
    end

    def handle_call({:set, key, value}, …
Run Code Online (Sandbox Code Playgroud)

elixir gen-server

2
推荐指数
1
解决办法
891
查看次数

GenServer 可以在 Elixir 中拥有自己的结构吗?

设想:

  • 我有一个简单GenServer的管理一些状态。
  • 目前,我正在使用map来管理我的 state。但随着我向该州添加更多数据,它正在增长。

问题:

  • 那么,为了获得一些编译时保证,struct我的GenServer模块中可以有 a吗?
  • 而且,如果是,这是一种正确的方法吗?
  • 如果没有,有哪些替代方案?

elixir gen-server

2
推荐指数
1
解决办法
544
查看次数

GenServer `handle_continue` 回调可以直接从另一个进程调用吗?

可以通过从同一 内的另一个回调返回来调用handle_continuea 的回调。GenServer{:noreply, state, {:continue, :foo}GenServer

如果回调后我有一小部分单独的步骤GenServer.init

defmodule MyGenServer do
  use GenServer

  def start_link(args \\ %{}) do
    GenServer.start_link(__MODULE__, args, [])
  end
  
  @impl true
  def init(args) do
    {:ok, args, {:continue, :foo}}
  end

  @impl true
  def handle_continue(:foo, state)
    case foo(state) do
      {:ok, state} ->
        {:noreply, state, {:continue, :bar}}

      {:error, :bar_not_set} ->
        {:noreply, state}
  end

  @impl true
  def handle_continue(:bar, state)
    state = bar(state)
    {:noreply, state}
  end

  defp foo(state = %{bar: _}) do
    {:ok, state}
  end
  defp …
Run Code Online (Sandbox Code Playgroud)

erlang elixir gen-server

2
推荐指数
1
解决办法
85
查看次数