Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir 有没有办法保持GenServer状态的持久性?_Elixir_Phoenix_Gen Server_Plug - Fatal编程技术网

Elixir 有没有办法保持GenServer状态的持久性?

Elixir 有没有办法保持GenServer状态的持久性?,elixir,phoenix,gen-server,plug,Elixir,Phoenix,Gen Server,Plug,我正在尝试使用GenServer实现一个计数器。其思想是每当客户端访问服务器时增加一个计数器,并在控制台中打印它。但是,每次访问后,GenServer状态重置或PID终止。有没有办法保持GenServer状态的持久性 代码如下: lib/myapp\u web/livecount.ex中的计数器文件 defmodule Counter do use GenServer # Client def start_link(integer \\ 0, opts \\ [])

我正在尝试使用GenServer实现一个计数器。其思想是每当客户端访问服务器时增加一个计数器,并在控制台中打印它。但是,每次访问后,GenServer状态重置或PID终止。有没有办法保持GenServer状态的持久性

代码如下:

lib/myapp\u web/livecount.ex中的计数器文件

defmodule Counter do
    use GenServer
    # Client
  
    def start_link(integer \\ 0, opts \\ []) when is_integer(integer) do
      GenServer.start_link(__MODULE__, integer, opts)
    end

    def add(pid) do
        GenServer.call(pid, :add)    
    end

    # Server
    @impl true
    def handle_call(:add, _from, state) do
        value = state + 1
        {:reply, "Dashboard hit: #{value}", value}
    end

    @impl true
    def init(value) do
        {:ok, value}
    end
end 

  def message(conn, _opts) do
    Code.require_file("lib/myapp_web/livecount.ex")
    {:ok, pid} = Counter.start_link()
    message = Counter.add(pid)
    IO.puts """
    Message: #{inspect(message)}
    """

    conn
  end 
我在lib/myapp\u web/endpoint.ex中添加了以下代码

defmodule Counter do
    use GenServer
    # Client
  
    def start_link(integer \\ 0, opts \\ []) when is_integer(integer) do
      GenServer.start_link(__MODULE__, integer, opts)
    end

    def add(pid) do
        GenServer.call(pid, :add)    
    end

    # Server
    @impl true
    def handle_call(:add, _from, state) do
        value = state + 1
        {:reply, "Dashboard hit: #{value}", value}
    end

    @impl true
    def init(value) do
        {:ok, value}
    end
end 

  def message(conn, _opts) do
    Code.require_file("lib/myapp_web/livecount.ex")
    {:ok, pid} = Counter.start_link()
    message = Counter.add(pid)
    IO.puts """
    Message: #{inspect(message)}
    """

    conn
  end 
以下是控制台中的消息:

[info] Sent 200 in 30ms
Message: "Dashboard hit: 1"

[info] CONNECTED TO Phoenix.LiveView.Socket in 143µs
  Transport: :websocket
  Serializer: Phoenix.Socket.V2.JSONSerializer
  Parameters: %{"_csrf_token" => "YyUeC3lgIQ83AlU3VBdoSg9PAwgYGl4QVQW_1PMHOjfg1s72wvoYHW2T", "_mounts" => "0", "vsn" => "2.0.0"}
[info] CONNECTED TO Phoenix.LiveView.Socket in 105µs
  Transport: :websocket
  Serializer: Phoenix.Socket.V2.JSONSerializer
  Parameters: %{"_csrf_token" => "TToLLhxmCAVIXXsJLVIJOjNYC2QIJy0bxNBzTVdB05HYH6VBKag5XjA_", "_mounts" => "0", "vsn" => "2.0.0"}
我想打印

Message: "Dashboard hit: 1"
Message: "Dashboard hit: 2"
Message: "Dashboard hit: 3"

每当客户端访问或重新加载页面时,增加每个用户访问的计数器。

这里有许多问题需要解决/改进

① 不应该在运行时内调用
code.require\u file/1
,除非绝对确定这是唯一的方法;默认情况下,位于
lib
中的常规文件可用
② 不应在常规代码中启动未受监控(无监控)的流程;在in
应用程序.ex中启动它
③ 为流程指定一个名称,以避免跟踪
pid

④ 您可能希望分别跟踪每个用户的访问;当前尝试将为每个用户提供一个计数器

这就是说,与下面的工作原理类似(假设流程已在其监督树中的
application.ex
中启动)

使用GenServer
def start_link(integer\\0)何时为_integer(integer)do
GenServer.start_链接(_模块,整数,名称:_模块)
结束
def add,do:GenServer.call(_模块__,:add)

def消息(conn,_opts)执行
message=Counter.add()
IO.inspect(信息,标签:“信息:”)
康涅狄格州
结束

要跟踪每个用户的计数器,可以将map
conn=>counter
保持在状态,或类似状态。

我花了一些时间才理解。它现在正在工作。非常感谢你。