提问人:Zack 提问时间:11/12/2023 更新时间:11/13/2023 访问量:37
Rails“每用户”互斥锁
Rails "per-user" mutex
问:
有没有办法在 Rails 中配置互斥锁,只阻止同一用户同时运行该代码(而不是阻止该代码部分中的所有并发)?
例如,我有以下方法:
def self.update(user, day, segment, category_id)
entry = find(user, day, segment)
if entry.nil?
entry = Entry.new(user: user, date: day, segment: segment)
end
entry[key_for_id(category_id)] = category_id
entry.save!
end
问题在于,如果同一个用户以某种方式同时执行此方法,则将创建两个单独的 Entry 对象(而不是第一次执行创建 Entry,第二次更新它)
创建一个基本的互斥锁将解决这个问题;但是,我不需要禁止关键部分的所有并发执行(我认为这可能会对性能产生重大影响),我只需要确保同一用户不能同时进入关键部分(这相对较少;但已经发生)。
有没有办法在 Rails 中做到这一点?
答:
0赞
Zack
11/13/2023
#1
正如@dbugger在评论和另一篇文章中所建议的那样:ActiveRecord 的 find_or_create* 方法从根本上存在缺陷吗?
解决方案是添加一个唯一索引和一个 .retry
class AddUniqueIndexToEntries < ActiveRecord::Migration[7.0]
def change
add_index :entries, [:user_id, :date, :segment], unique: true
end
end
begin
entry = find(user, day, time)
if entry.nil?
entry = Entry.new(user: user, date: day, segment: segment)
end
entry[key_for_id(category_id)] = category_id
entry.save!
rescue ActiveRecord::RecordNotUnique
retry
end
评论
save!