[英]Elixir GenServer cast and start_link
These are my first 2 hours of Elixir so it might be a noobish question but I have some issues with spawning up a GenServer
and casting it. 这是我开始
GenServer
Elixir的前2个小时,所以这可能是一个讨厌的问题,但是在生成GenServer
并进行投射时,我遇到了一些问题。 I'm using this module which watches for changes in a file in my system and, each time a new entry is added in that file, I want to cast the log to a gen server which analyzes it and does whatever is supposed to do based on it's findings. 我正在使用这个模块来监视系统中文件的更改,并且每次在该文件中添加新条目时,我都希望将日志投射到gen服务器上,该服务器对其进行分析并根据在它的发现上。
Here's the module that watches the changes: 这是监视更改的模块:
defmodule Test.Watcher do
use ExFSWatch, dirs: ["/var/log/"]
import Test.Receiver, only: [analyze_log: 2]
def callback(file_path, actions) do
if file_path == "/var/log/syslog" do
if :modified in actions do
#~~~~ WHERE DO I GET THIS pid FROM?
analyze_log pid, get_log
end
end
end
def get_log do
{log, _} = System.cmd("tail", ["-n", "1", "/var/log/syslog"])
log
end
end
The watcher works very well and it receives the new logs but I'm having a problem with Test.Receiver
which uses GenServer
. 观察者工作得很好,它接收新的日志,但我有一个问题
Test.Receiver
它使用GenServer
。
My first question is...where do I start this gen server? 我的第一个问题是...在哪里启动该发电服务器?
ExFSWatch
has it's own start
method and I can't override that. ExFSWatch
有它自己的start
方法,我无法覆盖它。 Do I call start_link
each time a new log passes in (I doubt that but I had to ask)? 每次传入新日志时,我是否都要调用
start_link
(我对此表示怀疑,但我不得不问)?
Ny all the examples I read I'm supposed to start it somewhere else, grab it's pid
and pass it as a param to the analyze_log
method so, if I'm right, my only remaining problem is finding out a good place to start the Test.Receiver
Genserver and grabbing it's pid so I can use it inside the callback
method. 我读过的所有示例都应该从其他地方开始,抓取它的
pid
并将其作为参数传递给analyze_log
方法,因此,如果我是对的,我唯一剩下的问题就是找到一个合适的位置开始Test.Receiver
Genserver并获取它的pid,因此我可以在callback
方法中使用它。
defmodule Test.Receiver do
use GenServer
def start_link do
GenServer.start_link(__MODULE__, :ok, [])
end
def analyze_log(pid, log) do
GenServer.cast(pid, {:analyze_log, log})
end
def init(:ok) do
{:ok, %{}}
end
def handle_cast({:analyze_log, log}, state) do
IO.puts log
{:noreply, state}
end
end
Ok, to expand on @Dogbert's answer and clear it out for others who are starting with Elixir I will provide the solution that worked out for me. 好的,要扩展@Dogbert的答案并将其清除给其他以Elixir开头的人,我将提供为我解决的解决方案。 It may not be the most elegant one as I lack the knowledge yet but works.
它可能不是最优雅的,因为我还没有知识,但是可以工作。
As Dogbert said, you need to register your GenServer
with a name and call it by that name. 正如Dogbert所说,您需要使用一个名称注册
GenServer
并使用该名称进行调用。 So I went to my main file and spawned a supervisor which keeps these listeners up and active like so: 因此,我进入主文件并生成了一个主管,该主管可以使这些侦听器保持活动状态,如下所示:
defmodule Test do
use Application
def start(_type, _args) do
import Supervisor.Spec, warn: false
Fail2ban.Watcher.start
children = [
# ... I have more here but let's keep it simple
supervisor(Test.Receiver, [Test.Receiver]),
]
opts = [strategy: :one_for_one, name: Test.Supervisor]
Supervisor.start_link(children, opts)
end
end
As you can see, the second parameter passed onto the supervisor call is the name under which I want to register this module. 如您所见,传递给超级用户调用的第二个参数是我要用来注册该模块的名称。 It may be anything you like I presume since I'm not very sure on that.
因为我不太确定,所以您可能会喜欢我想的任何东西。 This second parameter goes into my receiver's
start_link
and registers under that name: 第二个参数进入接收者的
start_link
并以该名称注册:
def start_link(name \\ nil) do
GenServer.start_link(__MODULE__, nil, [name: name])
end
With this in place now remember this method on the receiver that I had problems regarding the pid which I didn't know where to get from: 现在有了这个,请记住在接收器上使用此方法时,我遇到了关于pid的问题,而我不知道从哪里获取:
defmodule Test.Watcher do
use ExFSWatch, dirs: ["/var/log/"]
import Test.Receiver, only: [analyze_log: 2]
def callback(file_path, actions) do
if file_path == "/var/log/syslog" do
if :modified in actions do
# Instead of the pid, pass the name under which it was registered
analyze_log Test.Receiver, get_log
end
end
end
def get_log do
{log, _} = System.cmd("tail", ["-n", "1", "/var/log/syslog"])
log
end
end
Works for me, open to discussion and improvements. 为我工作,欢迎讨论和改进。 It's my 2nd day now of Elixir and I started to grasp it's ways of ticking.
现在是Elixir的第二天,我开始掌握它的滴答作响方式。 Coming from Python, Ruby, PHP myself it's a little
hard
different grabbing and passing information as parameters and state all the time but..I see the sun now. 来自Python,Ruby,PHP本身,在获取和传递信息作为参数和状态方面一直存在一些
困难
,但是..我现在看到了阳光。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.