嗨,我有这段代码
class Place < ActiveRecord::Base
def self.find_or_create_by_latlon(lat, lon)
place_id = call_external_webapi
result = Place.where(:place_id => place_id).limit(1)
result = Place.create(:place_id => place_id, ... ) if result.empty? #!
result
end
end然后我想做另一个模型或控制器
p = Post.new
p.place = Place.find_or_create_by_latlon(XXXXX, YYYYY) # race-condition
p.save但是,如果执行的操作是创建的,而在生产过程中,Place.find_or_create_by_latlon的p.place为0,则获取数据需要花费太多的时间。
如何在执行p.save之前强制等待响应?谢谢你的建议
发布于 2011-02-09 01:24:12
你说得对,这是一种竞赛条件,通常是由双击表单上的submit按钮的人触发的。如果遇到错误,您可能做的是回滚。
result = Place.find_by_place_id(...) ||
Place.create(...) ||
Place.find_by_place_id(...)有更优雅的方法来做这件事,但基本的方法在这里。
发布于 2013-03-21 13:54:38
我不得不处理一个类似的问题。在我们的后端中,如果用户不存在,则从令牌创建用户。在已经创建用户记录之后,将发送一个缓慢的API调用来更新用户信息。
def self.find_or_create_by_facebook_id(facebook_id)
User.find_by_facebook_id(facebook_id) || User.create(facebook_id: facebook_id)
rescue ActiveRecord::RecordNotUnique => e
User.find_by_facebook_id(facebook_id)
end
def self.find_by_token(token)
facebook_id = get_facebook_id_from_token(token)
user = User.find_or_create_by_facebook_id(facebook_id)
if user.unregistered?
user.update_profile_from_facebook
user.mark_as_registered
user.save
end
return user
end策略的步骤是首先从create方法中删除缓慢的API调用(在我的例子中是update_profile_from_facebook)。因为操作花费的时间太长,所以当您将操作作为创建调用的一部分时,会显著增加重复插入操作的机会。
第二步是向数据库列添加唯一约束,以确保不创建重复项。
最后一步是创建一个函数,在将重复插入操作发送到数据库的罕见情况下捕获RecordNotUnique异常。
这可能不是最优雅的解决方案,但它对我们有效。
发布于 2017-02-11 21:28:06
我在一个助手作业中按了这个键,它会反复地重试并得到错误,并最终清除它自己。我找到的最好的解释是在博客这里上找到的。要点是postgres保留了一个内部存储的值,用于增加被弄乱的主键。这对我来说是真的,因为我正在设置主键,而不仅仅是使用一个递增的值,所以这很可能是这样出现的。上面链接中的注释中的解决方案似乎是调用ActiveRecord::Base.connection.reset_pk_sequence!(table_name),这为我解决了这个问题。
begin
result = Place.where(:place_id => place_id).limit(1)
result = Place.create(:place_id => place_id, ... ) if result.empty? #!
rescue ActiveRecord::StatementInvalid => error
@save_retry_count = (@save_retry_count || 1)
ActiveRecord::Base.connection.reset_pk_sequence!(:place)
retry if( (@save_retry_count -= 1) >= 0 )
raise error
endhttps://stackoverflow.com/questions/4939349
复制相似问题