Как заблокировать таблицу, чтобы предотвратить создание записей в Rails? - PullRequest
0 голосов
/ 04 апреля 2019

Rails предлагает несколько способов блокировки отдельных записей. Это описано в Руководстве по интерфейсу запроса Active Record . Однако в настоящее время я нахожусь в следующем сценарии, где блокировка существующих записей не приведет к сокращению:

У меня есть модель Letter , которая имеет необязательный атрибут mailing_nr . Для рассылок я получу максимум mailing_nr и добавлю один. Затем создайте целую связку писем в транзакции, потому что все письма должны быть сохранены одновременно, или ни одной вообще.

Представьте себе сценарий, когда два пользователя генерируют почтовое сообщение в одно и то же время. Они оба получат самый высокий mailing_nr (я буду использовать 6 в качестве примера). Когда оба процесса сохранят свои записи, они получат один и тот же mailing_nr .

Как мне предотвратить вышеуказанный сценарий? Я думал о блокировке всей таблицы, чтобы предотвратить чтение и запись другими процессами. Однако я не знаю ни одного метода Rails, который будет это делать.

Вот мой пример кода:

# app/models/letter.rb
def self.create_mailing(template, report, options = {})
  options = options.dup
  options[:mailing_nr] = (Letter.maximum(:mailing_nr) || 0) + 1

  letters = nil
  transaction do
    letters = report.fetch_records.map do |record|
      new_with_template(template, record, options).tap(&:save!)
    end
  end

  letters
end

1 Ответ

0 голосов
/ 04 апреля 2019

Вы можете использовать Rails Lock , например:

letter = Letter.find(1)
letter.with_lock do
    #Do whatever you want, You have only single access here. No two persons can access this at a time 
end

Примечание Прочтите приведенную ссылку, потому что вы можете найти другой подход, который может быть лучше для вашей конкретной проблемы.

Обновление: вы можете использовать этот камень , но имейте в виду, что это может привести к тупику.

...