在 Elixir 1.7.4 上使用 Commanded 0.17.2 构建的应用程序经常耗尽内存。一项调查发现,内存泄漏似乎是由越来越多的聚合实例引起的,这些实例从未停止过。
有问题的聚合接收由外部系统触发的命令。在某些情况下,该execute
函数会返回一个事件,而在其他一些情况下,该命令应该被忽略并因此返回nil
(如docs所述)。
def execute(%RemoteThing{}, %ImportRemoteThing{deleted: true}), do: nil
似乎每次nil
返回而不是事件,聚合实例都无限期地保持活动状态。即使附加了超时和寿命,也会发生这种情况,这明确意味着其他事情:
defmodule RemoteThing.Lifespan do
@behaviour Commanded.Aggregates.AggregateLifespan
def after_event(_event), do: :stop
def after_command(_command), do: :stop
end
dispatch(
ImportRemoteThing,
to: RemoteThing,
lifespan: RemoteThing.Lifespan,
timeout: 15_000
)
我怀疑这是Commanded中的错误:
defp aggregate_lifespan_timeout(_context, []), do: :infinity
避免内存泄漏的一种方法是产生一个事件,即使没有人需要它。这将导致污染的持久事件存储而不是易失性内存,因此从长远来看可能会导致更大的问题。
我现在正在寻找一种方法来停止聚合实例,以防execute
函数返回nil
. 解决方法的每一个想法将不胜感激。