我正在尝试构建一个表,该表将充当第三方服务的批量同步队列。
以下方法应该说明一切;但要明确的是,它的目的是将status: :queued
的新可更新对象(多态关系)添加到delayed_syncs
表。
多态关系+ status
(updatable_id
,updatable_type
,status
)存在唯一性约束,这会导致队列中已存在可更新对象{{{ 1}}在这里失败并陷入救援区。
我看到的问题是,每当:queued status
生成的SELECT
被触发时,整个方法都会失败并显示:
的ActiveRecord :: StatementInvalid
错误。
我发现的信息表明在失败find_by
之后ROLLBACK
或RELEASE SAVEPOINT
,但我不确定如何在此处完成此操作。< / p>
上述方法:
INSERT
答案 0 :(得分:1)
您可以使用ActiveRecord
事务来确保全部或全无更新,而不是依赖逻辑的异常处理。
像这样:
ActiveRecord::Base.transaction do
DelayedSync.create!(updatable: updatable, status: :queued, action: action)
end
您仍然可以安全地利用rescue
来处理日志记录清理。
可以找到有关此详细信息的文档here。
答案 1 :(得分:0)
在进一步挖掘之后,我发现问题是由于我如何从after_save
回调调用此方法。在关闭交易之前,Rails会调用after_save
和after_destroy
个回调。 Postgres无法解决从此回调调用的ActiveRecord::RecordNotUnique
错误并尝试执行更多查询,因为它会使整个事务无效。我的解决方案是转换为after_commit
回调,它提供与after_save
和after_destroy
相同的控件和on: [:create, :destroy]
参数,并且有利于在<<>后执行 / strong>交易(无效或无效)已经关闭。
这篇博文有点过时了,但是底部附近的信息非常有用,仍然适用:http://markdaggett.com/blog/2011/12/01/transactions-in-rails/