Plugin rake task running multiple times - what are we missing?

I’m adding a rake task to the docker_manager plugin but I’m finding that the task is running twice when I invoke it. In its simplest form, I can add testing.rake to lib/tasks with the following contents:

# frozen_string_literal: true

desc "A test"
task "docker_manager:test do
  puts "test"
end

With this result:

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

I’ve confirmed that this is not a general problem with tasks in plugins by adding the same rake file to the poll plugin with this result:

/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

I haven’t yet been able to find anything obvious in the two plugins that might be preventing/causing this so I’m hoping someone might be able to offer suggestions for what could be preventing this in poll or causing it in docker_manager.

2 Likes

Did you solve this?

I’m getting a similar issue:

If I create a rake take in a plugin, say: lib/tasks/test.rake

with contents

desc "count posts"
task "test_rake:test" => :environment do
  puts "Number of posts on this forum is #{Post.count}"
end

and run: rake test_rake:test

The output is surprising to me:

Number of posts on this forum is 366
Number of posts on this forum is 366
Number of posts on this forum is 366

I’m making some kind of error here, I’m sure, but not sure what?

Why is this running more than once and how to stop it?

I get a similar issue in Production which is, of course, more of a serious concern.

1 Like

OK I managed to reduce the task to only running twice by removing the task from being loaded in the initialise block. Apparently it’s enough just to put it in /lib/tasks without having to load it.

That has brought me down to 1 repetition (now to a total of 2!) :sweat_smile:

Number of posts on this forum is 366
Number of posts on this forum is 366

This just repeats the experience of the OP.

2 Likes

Sadly not. Initially I had assumed it was something in core causing it to be loaded twice but seeing it only run once when added to the poll plugin seemed to refute that.

I’ve kind of forgotten now but I think using --trace might also be showing it only loading once. I might be wrong but if I recall correctly, the invoke and/or execute lines will appear twice if it’s loaded twice.

I failed to find any differences between docker_manager and poll or anything in core that would explain this difference in behaviour, and had basically given up when I made the post.

1 Like

I may be a bit late to the party :slight_smile:

I’m hitting the same issue in a new plugin, and searched a bit. It seems this issue hits other plugins too (e.g.: the official chat plugin), but I found a working solution to avoid the tasks being registered multiple times:

# Clear any previous registration
task('import_json:preview').clear 

# Task definition
desc 'Previews changes which would be applied by import_json'
task 'import_json:preview', [:file_path] => :environment do |_task, args|
  puts "Hello world!"
end

Clearing after the task description will prevent the task to be listed with rake --tasks, so it must be cleared before.

2 Likes

Does this mean you get the same result adding a task to it or that an already existing task in the plugin has this behaviour?

Thanks for the information! It feels a little hacky to have to clear it but it’s certainly a useful workaround.

I’ll mark your post as the solution for others’ convenience. Hopefully the broader cause can still be identified, I guess the question becoming: why are tasks registered twice in some plugins and not others?

Does this mean you get the same result adding a task to it or that an already existing task in the plugin has this behaviour?

While trying to understand why the tasks I developped in my own plugin was executed twice, I tested an existing task in the Chat plugin and it executed twice too.

I tested some tasks from other plugins too but can’t remember which ones. Some where executing once but there was nothing obvious about the difference of implementation.

Maybe there is something to do with the autoloading?

On a fresh plugin, the engine contains this line:

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

If I don’t autoload lib but lib/some_path to avoid autoloading lib/tasks, it seems better, but the downside is that it breaks autoloading (I stopped here). Which may lead to have a bunch of require_relative statements to compensate…

2 Likes

It certainly seems plausible that if there is already a mechanism for loading the tasks, this might cause them to be loaded a second time.

I wonder if using either of the following would deal with this (I think I would lean towards the latter since I don’t know what side effects there could be to autoloading once):

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