Плагин: задача rake выполняется несколько раз — что мы упускаем?

Я добавляю задачу rake в плагин docker_manager, но обнаружил, что задача выполняется дважды при её вызове. В самой простой форме я могу добавить файл testing.rake в lib/tasks со следующим содержимым:

# frozen_string_literal: true

desc "Тестовая задача"
task "docker_manager:test" do
  puts "test"
end

Результат:

/var/www/discourse# rake docker_manager:test --trace
** Invoke docker_manager:test (first_time)
** Execute docker_manager:test
test
test

Я подтвердил, что это не общая проблема с задачами в плагинах, добавив тот же файл rake в плагин poll. Результат:

/var/www/discourse# mv plugins/docker_manager/lib/tasks/testing.rake plugins/poll/lib/tasks/
/var/www/discourse# rake docker_manager:test --trace
** Invoke docker_manager:test (first_time)
** Execute docker_manager:test
test

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

Вы решили эту проблему?

У меня возникает похожая ошибка:

Если я создаю Rake-задачу в плагине, например: lib/tasks/test.rake

с содержимым:

desc "подсчитать публикации"
task "test_rake:test" => :environment do
  puts "Количество публикаций на этом форуме: #{Post.count}"
end

и запускаю: rake test_rake:test

Вывод меня удивляет:

Количество публикаций на этом форуме: 366
Количество публикаций на этом форуме: 366
Количество публикаций на этом форуме: 366

Я, наверное, где-то ошибаюсь, но не понимаю где именно.

Почему это выполняется больше одного раза и как это остановить?

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

Хорошо, мне удалось сократить задачу до двух запусков, исключив её загрузку в блоке инициализации. Оказывается, достаточно просто поместить её в /lib/tasks, без явной загрузки.

Это снизило количество повторений до одного (всего теперь два!) :sweat_smile:

Количество постов на этом форуме: 366
Количество постов на этом форуме: 366

Это просто повторяет опыт автора оригинального вопроса.

К сожалению, нет. Сначала я предположил, что проблема в ядре, из-за чего что-то загружается дважды, но тот факт, что при добавлении в плагин опросов оно запускается только один раз, вроде бы опровергает это.

Я немного забыл детали, но, кажется, использование флага --trace тоже показывает, что загрузка происходит только один раз. Возможно, я ошибаюсь, но, если память мне не изменяет, строки invoke и/или execute появятся дважды, если загрузка происходит дважды.

Мне не удалось найти никаких различий между docker_manager и poll или чего-либо в ядре, что могло бы объяснить такое различие в поведении, и я уже практически сдался, когда написал этот пост.

Возможно, я немного опоздал на вечеринку :slight_smile:

У меня возникла та же проблема в новом плагине, и я немного поискал. Похоже, что эта проблема затрагивает и другие плагины (например, официальный плагин чата), но я нашел рабочее решение, чтобы избежать многократной регистрации задач:

# Очистить любую предыдущую регистрацию
task('import_json:preview').clear 

# Определение задачи
desc 'Предварительный просмотр изменений, которые будут применены при импорте JSON'
task 'import_json:preview', [:file_path] => :environment do |_task, args|
  puts "Hello world!"
end

Очистка после описания задачи предотвратит отображение задачи в списке rake --tasks, поэтому её необходимо очистить до этого.

Это значит, что вы получаете тот же результат при добавлении задачи в него, или что уже существующая задача в плагине ведёт себя таким образом?

Спасибо за информацию! Чувствуется, что очистка — это немного хакинг, но это определённо полезное решение.

Я отмечу ваш пост как решение для удобства других. Надеюсь, что более широкую причину всё же можно будет выявить; вопрос сводится к следующему: почему задачи регистрируются дважды в некоторых плагинах, но не в других?

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

Пытаясь понять, почему задачи, которые я разработал в своём собственном плагине, выполнялись дважды, я протестировал существующую задачу в плагине Chat, и она тоже выполнилась дважды.

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

Возможно, это связано с автозагрузкой?

В новом плагине в движке есть такая строка:

config.autoload_paths << File.join(config.root, "lib")

Если я не автозагружаю lib, а lib/some_path, чтобы избежать автозагрузки lib/tasks, кажется, что становится лучше, но недостатком является то, что это нарушает автозагрузку (я остановился на этом). Это может привести к необходимости добавить множество операторов require_relative для компенсации…

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

Интересно, поможет ли использование одного из следующих вариантов решить эту проблему (я склоняюсь ко второму, так как не знаю, какие могут быть побочные эффекты от однократной автозагрузки):

config.autoload_once_paths << File.join(config.root, "lib")
config.autoload_lib(ignore: %w( tasks ))