我正在编写一个使用Exredis作为数据库的简单Web应用程序。 Exredis文档说用以下内容初始化客户端:
{:ok, conn} = Exredis.start_link
我的问题是,我应该在哪里放conn
?现在我在每个需要进行数据库查询的函数的顶部调用Exredis.start_link\1
,但感觉既嘈杂又低效。我可以传递conn
,但这只是将问题移到我的路由器上。
我希望在我的主应用程序启动时启动它,并在我的应用程序中重复使用单个连接。我可以将它作为工作人员添加到我的主管,但我无法弄清楚如何在我的应用程序的其余部分访问PID。
答案 0 :(得分:6)
我建议您创建一个处理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的更多信息。