标签: gen-server

Erlang,process_flag trap_exit从CLI中杀死了我的gen_server

我有这个与我合作的gen_server:

-module(user_info_provider).
-export([start_link/0, stop/0]).
-export([init/1, terminate/2, handle_info/2, handle_call/3, handle_cast/2,
 code_change/3]).
-export([request_user_info/2]).

-behaviour(gen_server).

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

stop() ->
    gen_server:cast(?MODULE, stop).

request_user_info(From,UserId) ->
    gen_server:cast(?MODULE, {request_user_info, From, UserId}).
%% Callback Functions
init(_) ->
    process_flag(trap_exit, true),
    io:format("I am ~w ~n", [self()]),
    {ok, null}.
%% @doc terminate
terminate(Reason, _LoopData) ->
    io:format("Terminating by ~w~n",[Reason]),
    {ok, null}.
handle_cast({request_user_info,From,UserId}, LoopData) ->
    {noreply, LoopData};
handle_cast(stop, LoopData) ->
    {stop, normal, LoopData}.
handle_info(_Info, State) ->
    {ok, State}.
code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
handle_call(_,_From,LoopData) ->
    {ok,ok,LoopData}.
Run Code Online (Sandbox Code Playgroud)

问题是,正如我接下来所展示的那样,如果我从cli中执行它就像 …

linux erlang command-line-interface gen-server

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

Erlang OTP主管

我正在从Erlang Programming一书中练习练习12-2.我有一个模块db_server_otp,它实现了一个OTP gen_server行为.作为一个独立的模块,我测试了它,它按预期工作.我现在必须为它添加一个主管.根据本章中的示例,我创建了一个模块db_server_sup,如下所示:

-module(db_server_sup).
-export([start/0,init/1]).
-behavior(supervisor).

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

init(_Arguments) ->
    DbServerOtp = {db_server_otp,                %% Id
                   {db_server_otp, start, []},   %% child process
                   permanent,                    %% restart 
                   30000,                        %% shutdown (ms)
                   worker,                       %% type
                   {db_server_otp}},             %% required modules
    {ok, 
     {{one_for_all,           %% terminate all children and restart
       5,                     %% max of n restarts in MaxSeconds
       3600},                 %% MaxSeconds (s)
      [DbServerOtp]}}.        %% child process list
Run Code Online (Sandbox Code Playgroud)

两个模块都位于同一个目录中,我用.beam文件编译这两个模块都在我启动erlang shell的同一个工作目录中.但是,使用erlang shell,我无法启动主管.

Erlang R13B03 (erts-5.7.4) [source] [64-bit] [smp:8:2] [rq:8] [async-threads:0] [hipe] …
Run Code Online (Sandbox Code Playgroud)

erlang gen-server erlang-supervisor

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

Erlang gen_server如何在另一个节点上启动gen_server?

我有一个Erlang应用程序,它有点太资源不足以留在一个节点上.我正在使gen_servers从一个进程转移到另一个进程 - 结果相对容易.我处于最后一个障碍:获取创建这些gen_servers的工厂进程以在远程节点而不是本地节点上生成它们.start_link的默认行为显然只在本地启动,但我没有看到任何更改它的选项.

似乎我必须要有创造力的解决方案,并想看看是否有人已经实现了这样的事情,并取得了任何成功.IOW,推荐的解决方案是什么?

编辑

我正在查看通过调用触发的调用链:

gen_server:start_link(?Module, Args, [])
Run Code Online (Sandbox Code Playgroud)

gen_server:START_LINK/3:

start_link(Mod, Args, Options) ->
    gen:start(?MODULE, link, Mod, Args, Options).
Run Code Online (Sandbox Code Playgroud)

创:启动/ 5:

start(GenMod, LinkP, Mod, Args, Options) ->
    do_spawn(GenMod, LinkP, Mod, Args, Options).
Run Code Online (Sandbox Code Playgroud)

创:do_spawn/5:

do_spawn(GenMod, link, Mod, Args, Options) ->
    Time = timeout(Options),
    proc_lib:start_link(?MODULE, init_it,
                        [GenMod, self(), self(), Mod, Args, Options], 
                        Time,
                        spawn_opts(Options));
Run Code Online (Sandbox Code Playgroud)

proc_lib:START_LINK/5:

start_link(M,F,A,Timeout,SpawnOpts) when is_atom(M), is_atom(F), is_list(A) ->
    Pid = ?MODULE:spawn_opt(M, F, A, ensure_link(SpawnOpts)),
    sync_wait(Pid, Timeout).
Run Code Online (Sandbox Code Playgroud)

这最终让我们感到有趣.有一个匹配的spawn_opt/4:

spawn_opt(M, F, A, Opts) when is_atom(M), is_atom(F), is_list(A) ->
    ...
    ... …
Run Code Online (Sandbox Code Playgroud)

erlang distributed erlang-otp nodes gen-server

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

为什么我们需要simple_one_for_one?

有人告诉我,simple_one_for_one对聊天应用程序非常有用,因为每个聊天客户端都是一个服务器进程(gen_server).这是正确的吗?

我想知道为什么我们需要它?为什么不创建一个中心服务器(gen_server)来处理所有聊天客户端通信?因为聊天客户端的数量可能非常大,所以只有一台服务器无法快速处理,导致系统速度变慢?

我认为创建像simple_one_for_one这样的服务器太多可能会占用过多的系统资源.我是一个新的OTP人,所以我真的需要解释这一点.

erlang erlang-otp gen-server erlang-supervisor

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

Gen 服务器错误 noproc

当我尝试使用 .shell 通过 shell 运行我的程序时,出现以下错误erlang.mk

=INFO REPORT==== 5-May-2016::05:47:57 ===
application: rad
exited: {bad_return,
            {{rad_app,start,[normal,[]]},
             {'EXIT',
                 {noproc,{gen_server,call,[rad_config,{lookup,port}]}}}}}
type: permanent
Eshell V6.4  (abort with ^G)
(rad@127.0.0.1)1> {"Kernel pid terminated",application_controller,"{application_start_failure,rad,{bad_return,{{rad_app,start,[normal,[]]},{'EXIT',{noproc,{gen_server,call,[rad_config,{lookup,port}]}}}}}}"}
Kernel pid terminated (application_controller) ({application_start_failure,rad,{bad_return,{{rad_app,start,[normal,[]]},{'EXIT',{noproc,{gen_server,call,[radheart: Thu May  5 05:47:58 2016: _coErlang is crashing .. (waiting for crash dump file)nf
ig,{lookup,porheart: Thu May  5 05:47:58 2016: tWould reboot. Terminating.}
]}}}}}})
make: *** [run] Error 1
Run Code Online (Sandbox Code Playgroud)

rad.app.src

{application, rad,
[
{description, "Awesome server written in Erlang"},
{vsn, "0.0.1"},
{registered, [rad_sup, rad_config]},
{modules, []}, …
Run Code Online (Sandbox Code Playgroud)

erlang gen-server

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

在handle_call/3行为(gen_server),Erlang/OTP的递归调用中出现超时错误

我正在尝试在回复之前对handle_call/3进行递归调用.但似乎不可能,因为timeout抛出了退出异常.您可以在下面看到代码和错误.

代码:

-module(test).
-behavior(gen_server).

%% API
-export([start_link/0,init/1,handle_info/2,first_call/1,second_call/1, handle_call/3, terminate/2]).

-record(state, {whatever}).

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

init(_Args) ->
  {ok, #state{}}.

handle_info(Data, State) ->
  {noreply, State}.

% synchronous messages
handle_call(_Request, _From, State) ->
  case _Request of
    first_call ->
      {reply, data1, State};
    second_call ->
      {reply, {data2, first_call(self())}, State}
  end.

first_call(Pid) ->
  gen_server:call(Pid, first_call).

second_call(Pid) ->
  gen_server:call(Pid, second_call).

terminate(_Reason, _State) ->
  ok.
Run Code Online (Sandbox Code Playgroud)

错误:

2> {_, PID} = test:start_link().
{ok,<0.64.0>}
3> test:second_call(PID).
** exception exit: {timeout,{gen_server,call,[<0.64.0>,second_call]}}
     in function  gen_server:call/2 (gen_server.erl, …
Run Code Online (Sandbox Code Playgroud)

erlang recursion erlang-otp gen-server

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

如何从Elixir GenServer处理程序中调用其他函数?

我有一个实现单个项目功能的GenServer,例如:

def handle_call({:sync, id}, _from, state) do
    ## update data
    {:reply, data, sync}
end
Run Code Online (Sandbox Code Playgroud)

现在我想为多个id处理这个功能,例如:

def handle_call({:sync_all, ids}, _from, state) do
    ## call sync for each id
    data = Enum.map(ids, fn(id) ->
        GenServer.call(self(), {:sync, id})
    end)
    ## Further reduce down data to stats
    {:reply, data, sync}
end
Run Code Online (Sandbox Code Playgroud)

然而,这并不能告诉我该过程试图调用自己.

我认为这必然是由于阻塞性质call.如果我castsync_all版本中使用,则会发生相同的情况.

所以我的问题是:如何GenServer从一个handle_call或一个handle_cast函数中调用其他任务?

erlang function elixir erlang-otp gen-server

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

Elixir GenServer handle_call回调返回类型

我正在实施一个GenServer,我很困惑.

我知道handle_cast是异步的,这意味着调用者不等待回复,我们返回一个这样的元组:{:noreply, new_state}.

我注意到我们也可以从中返回相同的元组handle_call.这是否意味着如果我有一个handle_call返回{:noreply, new_state},它不会返回任何东西但会同步?调用者的流程将等待GenServer.call命令,然后在handle_call函数完成后继续?

elixir gen-server

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

Elixir:使用 Dynamic Supervisor 启动孩子的正确方法

我正在尝试创建一个动态主管来启动子进程。我使用三个模块来做到这一点,一个是主模块,第二个是动态主管,第三个是 genserver。我没有收到任何错误,但我看不到任何正在运行的子进程。

这是我的代码。第一个是具有主要方法的模块

defmodule Simulator do
    def main(args) do
        {:ok, super_pid} = PersonManager.start_link(args)
        num_of_persons = 1
        start_persons(num_of_persons)
        IO.inspect PersonManager.count_children, label: "The Persons started in main method are"
    end

    def start_persons(num_of_persons) when num_of_persons >=1 do
        PersonManager.add_node(private_key, public_key, 0)
        start_persons(num_of_persons-1)    
    end
    # num_of_persons == 0 case handled
end   
Run Code Online (Sandbox Code Playgroud)

以下是动态Supervisor

defmodule PersonManager do
  use DynamicSupervisor

  def start_link(args) do
    DynamicSupervisor.start_link(__MODULE__, :ok, name: __MODULE__)
  end

  def add_node(private_key, public_key, num_of_coins) do
    # The code flow does come here, used inspect to check
    child_spec = {Person, {private_key, …
Run Code Online (Sandbox Code Playgroud)

elixir gen-server erlang-supervisor

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

GenServer上的Elixir非阻塞线程?

我正在努力完成一项简单的任务,但我遇到了很大的困难.

请假设我有一个GenServer,其中一个回调如下:

  @impl true
  def handle_call(:state, _, state) do
    # Something that would require 10 seconds
    newState = do_job()
    {:reply, newState, newState}
  end
Run Code Online (Sandbox Code Playgroud)

如果我是对的,GenServer.call(:server, :state)从客户端调用会阻塞服务器10秒钟,然后新状态将返回给客户端.

好.我希望服务器在不被阻止的情况下处理此任务.我使用任务尝试过,但Task.await/2Task.yield/2阻塞服务器.

我希望服务器不要阻塞,并在那10秒后,在客户端终端上接收结果.这怎么可能?

multithreading nonblocking elixir gen-server

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