![](/img/trans.png)
[英]What's the alternative of before_filter from Rails in Phoenix/Elixir?
[英]how to resume an elixir task from where it broke Elixir Phoenix
我们正在使用SeaweedFS ,它是一个文件系统来存储(图像)文件,它作为一个rest
api。 我们正在尝试将数据从一台服务器移动到另一台服务器。
有几个级别的数据目录。 存储图像的基本模式是
http://{server}:8888/ballymore-project-wave/snapshots/recordings/{year}/{month}/{day}/{hour}/00_00_000.jpg
目录的每一层都有自己的返回,以JSON
形式,如
{
"Path": "/ballymore-project-wave/snapshots/recordings/",
"Files": null,
"Directories": [
{
"Name": "2016",
"Id": 91874
},
{
"Name": "2017",
"Id": 1538395
}
],
"Limit": 100,
"LastFileName": "",
"ShouldDisplayLoadMore": false
}
上面的响应是针对当您试图获得年份的录音时,同样的响应是针对月、日和小时的。 当您获取单个小时时会发生轻微变化
{
"Path": "/ballymore-project-wave/snapshots/recordings/2016/11/02/01/",
"Files": [
{
"name": "00_00_000.jpg",
"fid": "29515,744a5a496b97ff98"
},
{
"name": "00_01_000.jpg",
"fid": "29514,744a5aa52ea3cf3d"
}
],
"Directories": null,
"Limit": 100,
"LastFileName": "02_15_000.jpg",
"ShouldDisplayLoadMore": true
}
现在我们需要将所有这些数据从一台服务器移动到另一台服务器。 我为它写了一个脚本
defp move_snapshots(exids) do
exids
|> Enum.each(fn (exid) ->
request_from_seaweedfs("#{@seaweedfs}/#{exid}/snapshots/recordings/", "Directories", "Name")
|> Enum.sort |> Enum.each(fn (year) ->
request_from_seaweedfs("#{@seaweedfs}/#{exid}/snapshots/recordings/#{year}/", "Directories", "Name")
|> Enum.sort |> Enum.each(fn (month) ->
request_from_seaweedfs("#{@seaweedfs}/#{exid}/snapshots/recordings/#{year}/#{month}/", "Directories", "Name")
|> Enum.sort |> Enum.each(fn (day) ->
request_from_seaweedfs("#{@seaweedfs}/#{exid}/snapshots/recordings/#{year}/#{month}/#{day}/", "Directories", "Name")
|> Enum.sort |> Enum.each(fn (hour) ->
request_from_seaweedfs("#{@seaweedfs}/#{exid}/snapshots/recordings/#{year}/#{month}/#{day}/#{hour}/?limit=3600", "Files", "name")
|> Enum.sort |> Enum.each(fn (file) ->
exist_on_seaweed?("/#{exid}/snapshots/recordings/#{year}/#{month}/#{day}/#{hour}/#{file}")
|> copy_or_skip("/#{exid}/snapshots/recordings/#{year}/#{month}/#{day}/#{hour}/#{file}")
end)
end)
end)
end)
end)
end)
end
这是主要功能, exids
表示所有相机字符串类型标识,例如,它是ballymore-project-wave
。
在上面的脚本中,我正在检查每个级别,如果有什么东西存在,我会更深入,直到最后,我检查它是否是一个有效的图像
defp exist_on_seaweed?(url) do
hackney = [pool: :seaweedfs_download_pool, recv_timeout: 30_000_000]
case HTTPoison.get("#{@seaweedfs}#{url}", ["Accept": "application/json"], hackney: hackney) do
{:ok, %HTTPoison.Response{status_code: 200, body: data}} -> {:ok, data}
_error ->
:not_found
end
end
defp copy_or_skip(:not_found, _path), do: :noop
defp copy_or_skip({:ok, data}, path) do
hackney = [pool: :seaweedfs_upload_pool]
case HTTPoison.post("#{@seaweedfs_new}#{path}", {:multipart, [{path, data, []}]}, [], hackney: hackney) do
{:ok, _response} -> Logger.info "[seaweedfs_save]"
{:error, error} -> Logger.info "[seaweedfs_save] [#{inspect error}]"
end
end
这一切正常但是当它由于某种原因崩溃或损坏时我有一个小问题,我需要为此提供指导/想法。 如您所见,如果相机exids
为 200 并且它在 100 或更少时exids
,它将恢复,但从一开始,我们无法在移动后删除旧服务器上的内容,直到完全移动,任何帮助将不胜感激。 此外,如果您认为代码中可能会有一些改进,这会有所帮助。
在您发布实际的堆栈跟踪或遇到的错误的详细信息之前,不可能确切地找出问题所在。 但是对于初学者来说,这里有一些可能会有所帮助的建议:
你应该把你的move_snapshots
方法分解成更容易理解的方法,也许使用像Enum.reduce/3
的递归方法,并调用你的copy_or_skip
方法作为基本情况。
尝试将您的copy_or_skip
方法实现包装在try/rescue
,挽救任何异常,记录它们并继续下一个。
defp copy_or_skip(args, path) do # Your Implementation rescue error -> Logger.error("Exception caught on #{inspect(path)}\\n#{inspect(error)}") end
您也可以浏览所有文件的列表,并将有效路径添加到诸如Que
或Toniq
类的作业处理库中的某个“Worker”。 该库将执行所有移动操作并将它们标记为成功或失败。 然后您可以返回查看哪些操作失败并找出导致它们的原因,或者自动重新启动失败的操作。
关于提高代码可靠性和性能的更多提示:
Stream
或更好的Flow
来划分任务并并行处理它们。Task
进程中执行实际的移动操作,最好由Supervisor
管理。 (可选地使用池)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.