我已将GenServer添加为
defmodule EvercamAdmin.Storage do
use GenServer
require Logger
def start_link(args) do
GenServer.start_link(__MODULE__, [args])
end
def init(args) do
Logger.info "Starting to create storage.json."
{:ok, 1}
end
end
我正在通过application.ex文件启动它,例如
def start(_type, _args) do
# List all child processes to be supervised
children = [
EvercamAdminWeb.Endpoint,
{EvercamAdmin.Storage, []}
]
opts = [strategy: :one_for_one, name: EvercamAdmin.Supervisor]
Supervisor.start_link(children, opts)
end
它工作正常,但是突然开始出现错误或** (EXIT) :badarg
我也尝试过更改.stark_link(__MODULE__, :ok, [args])
,但是错误是相同的。
更新:整个错误消息
Erlang/OTP 21 [erts-10.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Compiling 2 files (.ex)
[info] Running EvercamAdminWeb.Endpoint with cowboy 2.6.1 at http://localhost:4000
[info] Starting to create storage.json.
[info] Application evercam_admin exited: EvercamAdmin.Application.start(:normal, []) returned an error: shutdown: failed to start child: EvercamAdmin.Storage
** (EXIT) :badarg
** (Mix) Could not start application evercam_admin: EvercamAdmin.Application.start(:normal, []) returned an error: shutdown: failed to start child: EvercamAdmin.Storage
** (EXIT) :badarg
更新:完整的EvercamAdmin.Storage模块
defmodule EvercamAdmin.Storage do
use GenServer
require Logger
import Ecto.Query
@seaweedfs_new Application.get_env(:evercam_admin, :seaweedfs_new)
@seaweedfs_old Application.get_env(:evercam_admin, :seaweedfs_old)
@seaweedfs_oldest Application.get_env(:evercam_admin, :seaweedfs_oldest)
@proxy_host Application.get_env(:evercam_admin, :proxy_host)
@proxy_pass Application.get_env(:evercam_admin, :proxy_pass)
def start_link(args \\ []) do
GenServer.start_link(__MODULE__, args)
end
def init(args) do
Logger.info "Starting to create storage.json."
check_for_online_json_file()
|> whats_next(args)
{:ok, 1}
end
defp whats_next(:ok, ["refresh"]), do: whats_next(:start, ["refresh"])
defp whats_next(:ok, _), do: :noop
defp whats_next(:start, _args) do
construction_cameras =
Camera
|> where([cam], cam.owner_id in [13959, 109148])
|> preload(:owner)
|> Evercam.Repo.all
years = ["2015", "2016", "2017", "2018", "2019"]
servers = [@seaweedfs_new, @seaweedfs_old, @seaweedfs_oldest]
big_data =
Enum.map(construction_cameras, fn camera ->
servers =
Enum.map(servers, fn server ->
type = seaweefs_type(server)
attribute = seaweedfs_attribute(server)
url = "http://" <> server <> ":8888" <> "/#{camera.exid}/snapshots/recordings/"
year_values =
Enum.map(years, fn year ->
final_url = url <> year <> "/"
%{
"#{year}" => request_from_seaweedfs(final_url, type, attribute)
}
end)
%{
"#{server}" => year_values
}
end)
%{
camera_name: camera.name,
camera_exid: camera.exid,
oldest_snapshot_date: _snapshot_date(:oldest, camera),
latest_snapshot_date: _snapshot_date(:latest, camera),
servers: servers
}
end)
File.write("storage.json", Poison.encode!(big_data), [:binary])
seaweedfs_save(big_data, 1)
end
defp seaweefs_type(@seaweedfs_new), do: "Entries"
defp seaweefs_type(_), do: "Directories"
defp seaweedfs_attribute(@seaweedfs_new), do: "FullPath"
defp seaweedfs_attribute(_), do: "Name"
defp _snapshot_date(atom, camera) do
with {:ok, %HTTPoison.Response{body: body, status_code: 200}} <- HTTPoison.get(
"https://media.evercam.io/v2/cameras/#{camera.exid}/recordings/snapshots/#{atom |> to_string}?api_id=#{camera.owner.api_id}&api_key=#{camera.owner.api_key}"
)
do
{:ok, %{"created_at" => date}} = Jason.decode(body)
date
else
_ ->
""
end
end
def check_for_online_json_file do
with {:ok, %HTTPoison.Response{status_code: 200}} <- HTTPoison.get(
"http://#{@seaweedfs_new}:8888/evercam-admin3/storage.json",
["Accept": "application/json"],
hackney: [pool: :seaweedfs_download_pool],
proxy: {@proxy_host, 80},
proxy_auth: {"fixie", @proxy_pass}
)
do :ok
else
_ ->
:start
end
end
def request_from_seaweedfs(url, type, attribute) do
hackney = [pool: :seaweedfs_download_pool, recv_timeout: 15000]
with {:ok, response} <- HTTPoison.get(url, ["Accept": "application/json"], hackney: hackney, proxy: {@proxy_host, 80}, proxy_auth: {"fixie", @proxy_pass}),
%HTTPoison.Response{status_code: 200, body: body} <- response,
{:ok, data} <- Poison.decode(body),
true <- is_list(data[type]) do
Enum.map(data[type], fn(item) -> item[attribute] |> get_base_name(type, attribute) end)
else
_ -> []
end
end
defp get_base_name(list, "Entries", "FullPath"), do: list |> Path.basename
defp get_base_name(list, _, _), do: list
def seaweedfs_save(_data, _tries = 4), do: :noop
def seaweedfs_save(data, tries) do
hackney = [pool: :seaweedfs_upload_pool]
case HTTPoison.post("http://#{@seaweedfs_new}:8888/evercam-admin3/storage.json", {:multipart, [{"/evercam-admin3/storage.json", Jason.encode!(data), []}]}, [], hackney: hackney, proxy: {@proxy_host, 80}, proxy_auth: {"fixie", @proxy_pass}) do
{:ok, response} -> response
{:error, error} ->
seaweedfs_save(data, tries + 1)
Logger.info "[seaweedfs_save] [#{inspect error}]"
end
end
end
答案 0 :(得分:0)
{EvercamAdmin.Storage, []}
(基本上与EvercamAdmin.Storage
相同)在调用Supervisor.start_link/2
时的子参数告诉Supervisor
调用EvercamAdmin.Storage.start_link/1
不带参数,而您的实现只需要一个参数(arity恰好是1
。)
args
通常是一团糟。您期望args
,然后将其包装在一个列表中(目的是什么?),然后将其传递给init/1
,以后再也不用。应该执行以下操作:
defmodule EvercamAdmin.Storage do
use GenServer
require Logger
def start_link(args \\ []), # accept no params
do: GenServer.start_link(__MODULE__, args)
def init(args) do
Logger.info "Starting to create storage.json."
{:ok, args} # What did `1` suppose to mean?
end
end
并致电Supervisor.start_link/2
:
children = [
EvercamAdminWeb.Endpoint,
EvercamAdmin.Storage # `start_link` now accepts empty args
]