ruby-on-rails Rails“每用户”互斥

q0qdq0h2  于 7个月前  发布在  Ruby
关注(0)|答案(1)|浏览(89)

有没有一种方法可以在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和第二次更新它相反)
创建一个基本的Mutex可以解决这个问题;但是,我不需要禁止临界区的 * 所有 * 并发执行(我假设这会对性能产生重大影响),我只需要确保同一个 * 用户 * 不能并发进入临界区(这相对罕见;但已经发生了)。
在Rails中有办法做到这一点吗?

sd2nnvve

sd2nnvve1#

正如@dbugger在评论和另一篇文章中建议的那样:Are ActiveRecord's find_or_create* methods fundamentally flawed?
解决方案是添加一个唯一索引和一个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

字符串

相关问题