Это проблема, с которой я тоже столкнулся.
Краткий ответ : Нет простого способа обойти эту проблему. Все touch
находятся в одной транзакции, поэтому тупик.
Длинный ответ : Я полагаю, вам нужны сенсорные объекты для аннулирования некоторых (зависимых) кэшей. Обычно рекомендуемое использование touch
работает только для ограниченного количества «отношений». Например. аннулирование статьи при обновлении комментария.
Моим решением была асинхронная коллекция (с использованием задания sidekiq) объектов БД, которые должны быть признаны недействительными. Я написал для него собственную логику управления, которая определяет, какие (другие) объекты должны быть признаны недействительными при изменении объекта. Например. комментарий ==> статья.
Таким образом, мы получили более подробный способ аннулирования зависимых объектов. Кроме того, я объявил недействительным использование Model.update_all
, которое было намного быстрее, чем «цепочка касаний». Это решило наши проблемы взаимоблокировок (и добавило многословность и производительность к нашему аннулированию кэша).
Дополнительный совет: не используйте updated_at
. Это очень спорно, если объект DB действительно изменился, потому что другой объект изменился. Перезапись модели cache_key
позволяет легко определить пользовательский ключ кэша, например "#{id}-#{valid_from}"
. valid_from
может быть меткой времени, которую вы определяете в своих моделях (и которую вы используете вместо updated_at
).