delayed_job: одна работа на одного арендатора за раз? - PullRequest
3 голосов
/ 12 марта 2019

У меня есть приложение для нескольких арендаторов Rails с несколькими работниками delayed_job.

Чтобы избежать дублирования работы, специфичной для арендатора, я бы хотел отделить рабочих друг от друга таким образом, чтобы каждый работал натолько одна специфическая для арендатора задача за один раз.

Я думал об использовании (именованного) столбца queue и добавлении «tenant_1», «tenant_2» и так далее.К сожалению, очереди должны именоваться во время настройки, поэтому этот принцип недостаточно гибок для многих арендаторов.

Есть ли способ настроить способ, с помощью которого delayed_job выбирает следующую задачу?Есть ли другой способ определить область?

Ответы [ 2 ]

2 голосов
/ 15 марта 2019

Лучше всего, вероятно, использовать специальное решение, которое реализует распределенную блокировку - по сути, все работники работают нормально и вытаскивают из обычных очередей, но перед выполнением проверки работы с другой системой (Redis, RDBMS, API и т. Д.)чтобы убедиться, что ни один другой работник еще не выполняет работу для этого арендатора.Если этот арендатор не работает, установите замок для данного арендатора и выполните работу.Если арендатор заблокирован, не выполняйте работу.Это ваш вызов по многим деталям реализации, таким как переход к другой работе, повторное добавление в очередь в конце очереди, решение о том, считается ли это неудачей и привязка ли его к пределам повторных попыток, или что-то ещеполностью.Это довольно открытый, поэтому я оставлю вам детали, но вот несколько советов:

  • Наследование будет вашим другом;определите это поведение на базовом задании и унаследуйте его на заданиях, которые, как вы ожидаете, будут выполняться вашими работниками.Это также позволяет вам настроить поведение, если у вас есть «особые» случаи для определенных заданий, которые возникают, не нарушая ничего другого.
  • Предполагая, что вы не используете ActiveJob (так как он не был упомянут), прочитайтена delayed_job хуках: https://github.com/collectiveidea/delayed_job/#hooks - они могут быть подходящим и / или полезным инструментом
  • Ознакомьтесь с некоторыми различиями и компромиссами в стратегиях пессимистической и оптимистической блокировки - этот ответХорошая отправная точка: Оптимистическая или пессимистическая блокировка
  • Ознакомьтесь с общими практиками, касающимися концепции распределенных блокировок, чтобы вы могли выбрать для себя лучшие инструменты и стратегии (для этого не нужнобудь сумасшедшим сложным решением, достаточно простой таблицы в базе данных, в которой хранится идентификатор арендатора, но вы захотите рассмотреть случаи сбоев - например, как управлять заброшенными блокировками)

Серьезно подумайте не делать этого;действительно ли это строго необходимо для правильной работы системы?Если это так, это, вероятно, указывает на основной недостаток вашей модели данных или на то, как вы структурировали преобразования вокруг этих данных.Стремитесь к ACIDity в своем приложении, думая об операциях с данными, и вы можете избежать многих из этих проблем.Есть причина, по которой это не общедоступная функция «из коробки» для фоновых исполнителей.Если есть основной недостаток, он не просто укусит вас в этой проблеме, но в чем-то другом - гарантировано!

0 голосов
/ 15 марта 2019

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

ExpiredOrderCleaner = Struct.new(:tenant_id) do
  def perform
    Order.where(tenant_id: tenant_id).expired.delete_all
  end
end

Tenant.each do |tenant|
  Delayed::Job.enqueue ExpiredOrderCleaner.new(tenant.id)
end

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

эти рекомендации верны для любого фонового работника.

  • Сделайте свою работу идемпотентной и транзакционной означает, что ваша работаможет безопасно выполнять несколько раз
  • Embrace Concurrency проектировать ваши задания, чтобы вы могли запускать множество из них параллельно

вашработа будет намного проще, если вы используете квартиру драгоценный камень и активную работу обертки.см. примеры оттуда документов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...