如何每秒发出请求而无需等待GenServer Elixir中的请求完成
这与上面的问题有关,所以我已经发布了链接.
This is related to the above question, So I have posted the link.
我已经做了这样的GenServer工作者.
I have made such GenServer worker.
这是我的整个GenServer
this my whole GenServer
defmodule Recording.Worker do
use GenServer
require Logger
def start_link(opts) do
{id, opts} = Map.pop!(opts, :id)
GenServer.start_link(__MODULE__, opts, name: id)
end
def init(state) do
schedule_fetch_call(state.sleep)
{:ok, state}
end
def handle_info(:jpeg_fetch, state) do
{for_jpeg_bank, running} =
make_jpeg_request(state.camera)
|> running_map()
IO.inspect("request")
IO.inspect(DateTime.utc_now())
put_it_in_jpeg_bank(for_jpeg_bank, state.camera.name)
schedule_fetch_call(state.sleep)
{:noreply, Map.put(state, :running, running)}
end
def get_state(pid) do
GenServer.call(pid, :get)
end
def handle_call(:get, _from, state),
do: {:reply, state, state}
defp schedule_fetch_call(sleep),
do: Process.send_after(self(), :jpeg_fetch, sleep)
defp make_jpeg_request(camera) do
headers = get_request_headers(camera.auth, camera.username, camera.password)
requested_at = DateTime.utc_now()
Everjamer.request(:get, camera.url, headers)
|> get_body_size(requested_at)
end
defp get_body_size({:ok, %Finch.Response{body: body, headers: headers, status: 200}}, requested_at) do
IO.inspect(headers)
{body, "9", requested_at}
end
defp get_body_size(_error, requested_at), do: {:failed, requested_at}
defp running_map({body, file_size, requested_at}),
do:
{%{datetime: requested_at, image: body, file_size: file_size},
%{datetime: requested_at}}
defp running_map({:failed, requested_at}), do: {%{}, %{datetime: requested_at}}
defp get_request_headers("true", username, password),
do: [{"Authorization", "Basic #{Base.encode64("#{username}:#{password}")}"}]
defp get_request_headers(_, _username, _password), do: []
defp put_it_in_jpeg_bank(state, process) do
String.to_atom("storage_#{process}")
|> Process.whereis()
|> JpegBank.add(state)
end
end
我正在尝试每秒发出一个HTTP请求.即使在使用GenSever并以DynamicSupervisor(例如
I am trying to make an HTTP request per second. even while using GenSever and starting it with a DynamicSupervisor such as
General.Supervisor.start_child(Recording.Worker, %{id: String.to_atom(detailed_camera.name), camera: detailed_camera, sleep: detailed_camera.sleep})
这部分
def handle_info(:jpeg_fetch, state) do
{for_jpeg_bank, running} =
make_jpeg_request(state.camera)
|> running_map()
IO.inspect("request")
IO.inspect(DateTime.utc_now())
put_it_in_jpeg_bank(for_jpeg_bank, state.camera.name)
schedule_fetch_call(state.sleep)
{:noreply, Map.put(state, :running, running)}
end
仍在等待上一个请求完成,并且变为(完成请求所花费的时间)/每个请求每秒(不是请求).
still waiting for the previous request to complete and it becomes (the time request took to get complete) / per request not request per second.
IO.inspect的结果例如
the results of IO.inspect are such as
"request"
~U[2020-12-30 05:27:21.466262Z]
"request"
~U[2020-12-30 05:27:24.184548Z]
"request"
~U[2020-12-30 05:27:26.967173Z]
"request"
~U[2020-12-30 05:27:29.831532Z]
Elixir中是否有可能不使用spawn而 handle_info
继续运行而无需等待上一个请求或上一个方法完成的方式?
is there any way possible in Elixir that without using spawn, handle_info
just keep running without waiting for the previous request or previous method to complete?
一个人可能会启动带有两个子代的 Supervisor
: DynamicSupervisor
进程和将产生工作进程的进程.后者每秒会产生一个工人,并立即重新安排工时.
One might start the Supervisor
carrying two children: the DynamicSupervisor
process and the process that would spawn workers. The latter would spawn a worker once per second and immediately reschedule.
defmodule MyApp.Supervisor do
use Supervisor
def start_link(),
do: Supervisor.start_link(__MODULE__, nil, name: __MODULE__)
@impl Supervisor
def init(nil) do
children = [
{DynamicSupervisor, strategy: :one_for_one, name: MyApp.DS},
{MyApp.WorkerStarter, [%{sleep: 1_000}]}
]
Supervisor.init(children, strategy: :one_for_one)
end
end
Worker Starter
defmodule MyApp.WorkerStarter do
use GenServer
def start_link(opts) do
GenServer.start_link(__MODULE__, opts)
end
def init(state) do
schedule_fetch_call(state)
{:ok, state}
end
def handle_info(:request, state) do
schedule_fetch_call(state.sleep)
DynamicSupervisor.start_child(MyApp.DS, {MyApp.Worker, [state])
{:noreply, state}
end
defp schedule_fetch_call(state),
do: Process.send_after(self(), :request, state.sleep)
end
工人
defmodule MyApp.Worker do
use GenServer
def start_link(state),
do: GenServer.start_link(__MODULE__, state)
def init(state) do
perform_work(state)
{:stop, :normal}
end
defp perform_work(state), do: ...