我正在构建自己的代码库,用于处理ElasticSearch,使用Tirexs包。这是我第一次深入研究宏,依赖,使用,导入以及Elixir提供的其他一些最先进的功能。
为此我定义了一个Document
结构,看起来大致如此,(/lib/data/document.ex
)
defmodule Document do
use Document.ORM
import Document.Builder, only: [build_document: 2]
import Document.Builder.Validations, only: [is_document_valid?: 1, collect_errors: 1]
defstruct [valid?: false, errors: nil, fields: %{}]
def something do
# uses imported functions from Document.Builder and Documen.Builder.Validations
end
end
Document
模块然后使用Document.ORM
模块中的其他几个函数,这些函数似乎不是错误的原因。
我的错误如下
Compilation failed because of a deadlock between files.
dataobj_1 | The following files depended on the following modules:
dataobj_1 |
dataobj_1 | web/controllers/document_controller.ex => Document
dataobj_1 | lib/data/document/builder.ex => Document.Builder.AuxiliarBuilder
dataobj_1 | lib/data/document.ex => Document.Builder
dataobj_1 | lib/data/document/orm/bulk/utils.ex => Document
dataobj_1 | lib/data/document/builder/auxiliar.ex => Document
有一个我不知道如何接近的僵局,我确定我做错了什么。
第一个依赖项document_controller
出现(我认为),因为它在不同的地方都引用了模块Document
和%Document
结构:
defmodule Data.DocumentController do
use Data.Web, :controller
def create(conn, %{"document" => document_params}) do
{:ok, doc} = document_params
|> Document.new
case Document.save(doc) do
{:ok, record} ->
conn
|> put_status(201)
|> render(Data.DocumentView, "document.json", payload: Document.find(record._id))
{:error, map_of_errors} ->
conn
|> put_status(422)
|> render(Data.ErrorView, "422.json", errors: map_of_errors)
end
end
def update(conn, %{"id" => id, "document" => document}) do
case Document.update(id, document) do
%Document{valid?: false, errors: errors} ->
conn
|> put_status(422)
|> render(Data.ErrorView, "422.json", errors: errors)
docset ->
conn
|> put_status(200)
|> render(Data.DocumentView, "update.json", payload: docset)
end
end
其他依赖项也指模块和结构,所以我认为死锁与此有关。但我迷失了该怎么做。
如果有必要,我可以分享更多代码,但要开始提问,我认为这已经足够了。
提前致谢!
答案 0 :(得分:4)
你有循环依赖。
Document -> Document.Builder -> Document.AuxiliarBuilder -> Document
一般来说,您应该避免使用子模块(Document.Builder
,Document.AuxiliarBuilder
)来调用其父模块(Document
)。听起来你需要从Document
中提取这些函数并将它们放在别处。
注意:Elixir实际上没有父模块和子模块的概念。我只是在这里使用这些词语,因为这就是我的想法。
答案 1 :(得分:0)
显然循环依赖是因为结构的定义,即%Document
,并且与模块名称混淆。
将结构定义移动到它自己的单独文件中(前几行here是提示),并将模块名称从Document
更改为Data.Document
(%Data.Document
)足以解决所有循环依赖。