使用 elixir Processes 和 Supervisors 改进服务方法
Improve service method with elixir Processes and Supervisors
我正在构建一个将向两个外部 API 发出请求的服务。结果保存在本地数据库中。
大致来说,该方法应该是这样工作的:
def make_requests(conn, params) do
case Service1.request(params) do
{:ok, response1 } ->
case Service2.request(params) do
{:ok, response2 } ->
conn
|> Repo.insert(response1)
|> Repo.insert(response2)
|> render("show.json")
{:error, message} ->
conn |> render("error.json")
end
{:error, message } ->
conn |> render("error.json")
end
end
elixir 的新手,我一直在阅读有关进程和主管的信息。我的问题是:在这里使用它们是否有意义?我可以通过在此处实施它们来提高方法的速度、性能或提高容错能力吗?
既然你具体问这是否可以提高性能或容错性,我认为答案是肯定的。您可以使用 Task.async 并行执行请求,因为这些请求看起来并不相互依赖。数据库插入也是如此。我可能会在这里使用 Task.Supervisor。您还可以将其配置为在失败时重试,只是要注意确保请求和数据库插入是幂等的,不要以重复结束。
例如,
import Supervisor.Spec
children = [
supervisor(Task.Supervisor, [[name: ExampleApp.TaskSupervisor, restart: :transient]]),
]
{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
然后,
{:ok, pid} = Task.Supervisor.start_child(ExampleApp.TaskSupervisor, fn ->
{:ok, response} = Service1.request(params)
Repo.insert(response)
end)
{:ok, pid} = Task.Supervisor.start_child(ExampleApp.TaskSupervisor, fn ->
{:ok, response} = Service2.request(params)
Repo.insert(response)
end)
我正在构建一个将向两个外部 API 发出请求的服务。结果保存在本地数据库中。
大致来说,该方法应该是这样工作的:
def make_requests(conn, params) do
case Service1.request(params) do
{:ok, response1 } ->
case Service2.request(params) do
{:ok, response2 } ->
conn
|> Repo.insert(response1)
|> Repo.insert(response2)
|> render("show.json")
{:error, message} ->
conn |> render("error.json")
end
{:error, message } ->
conn |> render("error.json")
end
end
elixir 的新手,我一直在阅读有关进程和主管的信息。我的问题是:在这里使用它们是否有意义?我可以通过在此处实施它们来提高方法的速度、性能或提高容错能力吗?
既然你具体问这是否可以提高性能或容错性,我认为答案是肯定的。您可以使用 Task.async 并行执行请求,因为这些请求看起来并不相互依赖。数据库插入也是如此。我可能会在这里使用 Task.Supervisor。您还可以将其配置为在失败时重试,只是要注意确保请求和数据库插入是幂等的,不要以重复结束。
例如,
import Supervisor.Spec
children = [
supervisor(Task.Supervisor, [[name: ExampleApp.TaskSupervisor, restart: :transient]]),
]
{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
然后,
{:ok, pid} = Task.Supervisor.start_child(ExampleApp.TaskSupervisor, fn ->
{:ok, response} = Service1.request(params)
Repo.insert(response)
end)
{:ok, pid} = Task.Supervisor.start_child(ExampleApp.TaskSupervisor, fn ->
{:ok, response} = Service2.request(params)
Repo.insert(response)
end)