我遇到了一个问题,当PG失败不同步时(众所周知的问题)(IntelliJ documentation)。
PG失败不同步,id序列停止递增并引发ActiveRecord::RecordNotUnique
错误。
但是这里提出的所有解决方案(我发现的所有解决方案)都提出了一些手动解决方案 - 要么在控制台中执行某些操作,要么运行自定义rake任务。
然而,我发现这对于制作来说不满意:每次发生,用户都会得到500,而管理服务器的人应该可以节省一天。 (根据测试数据由于某种原因,在我的情况下可能经常发生)。
所以我想修补ActiveRecord Base类以捕获此特定错误并将其解救。
我有时在控制器中使用这个逻辑:
class ApplicationController < ActionController::Base
rescue_from ActionController::ParameterMissing, ActiveRecord::RecordNotFound do |e|
# some logic here
end
end
然而,在这里我不需要重试。另外,我想不要深入猴子修补,例如,不要覆盖Base创建方法。
所以我在考虑这样的事情:
module ActiveRecord
class Base
rescue ActiveRecord::RecordNotUnique => e
if e.message.include? '_pkey'
table =e.message.match(//) #regex to define table
ActiveRecord::Base.connection.reset_pk_sequence!(table)
retry
else
raise
end
end
end
但它很可能不起作用,因为我不确定Rails / Ruby是否会理解它要求重试的内容。
有没有解决方案?
P.S。对于没有手动命令行命令和没有非服务用户的序列整体问题的相关解决方案也不受欢迎。
答案 0 :(得分:1)
回答你问的问题,不。 rescue
只能在begin..end
块或方法正文中使用。
begin
bad_method
rescue SomeException
retry
end
def some_method
bad_method
rescue SomeException
retry
end
rescue_from
只是一个框架帮助器方法,因为执行在控制器中是间接的。
要回答这个问题,请确定 。您可以使用create_or_update
/ rescue
覆盖retry
。
module NonUniquePkeyRecovery
def create_or_update(*)
super
rescue ActiveRecord::RecordNotUnique => e
raise unless e.message.include? '_pkey'
self.class.connection.reset_pk_sequence!(self.class.table_name)
retry
end
end
ActiveSupport.on_load(:active_record) do
include NonUniquePkeyRecovery
end