微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

有没有办法保持 GenServer 状态持久化?

如何解决有没有办法保持 GenServer 状态持久化?

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

代码如下:

lib/myapp_web/livecount.ex 中的计数器文件

const props = {
  classes: 'this is a value',theme: 'foo',hidden: false,otherProp1: 'other 1',otherProp2: {
    nestedProp: 'nested value',},};

const { classes,theme,hidden,...other } = props;

console.log(classes);
console.log(theme);
console.log(hidden);
console.log(other);

我在 lib/myapp_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_","vsn" => "2.0.0"}

每当客户访问或重新加载页面时,并增加每次所有用户访问的计数器。

解决方法

这里有很多需要修复/改进的地方。

① 不应在运行时调用 Code.require_file/1,除非绝对确定这是唯一的方法;位于 lib 中的常规文件默认可用
② 不应从常规代码中启动不受监控(无监督)的进程;在 application.ex
supervision tree 中启动它 ③ 为进程命名以避免跟踪pid
④ 您可能希望分别跟踪每个用户的访问;当前的尝试将为每个用户提供一个计数器

也就是说,有点像下面的工作(假设流程已在其监督树中的 application.ex 中启动。)

  use GenServer
 
  def start_link(integer \\ 0) when is_integer(integer) do
    GenServer.start_link(__MODULE__,integer,name: __MODULE__)
  end

  def add,do: GenServer.call(__MODULE__,:add)

  def message(conn,_opts) do
    message = Counter.add()
    IO.inspect(message,label: "Message:")
    conn
  end 

要跟踪每个用户的计数器,可以在该州持有地图 conn => counter 等。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。