我正在编写一个使用 Exredis 作为数据库的简单 Web 应用程序。 Exredis 文档说用以下方法初始化客户端:

{:ok, conn} = Exredis.start_link

我的问题是,我应该把 conn 放在哪里?现在我在需要进行数据库查询的每个函数的顶部调用 Exredis.start_link\1 ,但这感觉既嘈杂又低效。我可以传入 conn,但这只会将问题转移到我的路由器上。

我想在我的主应用程序启动时启动它一次,然后在我的应用程序中简单地重用单个连接。我可以将它作为 worker 添加到我的主管,但我无法弄清楚如何在我的应用程序的其余部分访问 PID。

最佳答案

我建议您创建一个处理 redis 的单个模块,而不是传递 conn。您可能想要两种方式(首选第二种方式):

1. 每次查询redis都会启动和关闭一个新的连接:

    defmodule Redis do
        @redis_host "192.168.0.10"
        @redis_port 6379

        def query( ... ) do
            {:ok, conn} = Exredis.start_link( @redis_host, @redis_port )
            r = Exredis.query( conn, ... )
            Exredis.stop( conn )
            r
        end
    end

2. 更好的是将 Exredis 包装在 GenServer 中(首选解决方案):
    defmodule Redis do
        use GenServer

        @redis_host "192.168.0.10"
        @redis_port 6379

        # External API

        def start_link( state ) do
            GenServer.start_link( __MODULE__, state, name: __MODULE__ )
        end

        def query( ... ) do
            GenServer.call __MODULE__, { :query, ... }
        end

        # GenServer implementation

        def init( state ) do
            {:ok, conn} = Exredis.start_link( @redis_host, @redis_port )

            # conn becomes state available in handle_call / terminate
            {:ok, conn}
        end

        def handle_call( { :query, ... }, conn ) do
            r = Exredis.query( conn, ... )
            { :reply, r, conn }
        end

        def terminate( _reason, conn ) do
            Exredis.stop( conn )
        end
    end

您将上述 GenServer 添加到您的主管(将 nil 作为初始状态传递给它)。然后你坚持使用外部 API。您永远不会直接与 GenServer 打交道,这使得将来更容易更改和发展您的模块。您可以阅读有关 GenServers here 的更多信息。

关于elixir - 我在哪里存储长时间运行的子进程的 PID?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37009942/

10-11 18:39