nanoc / features

Collection of feature requests
2 stars 1 forks source link

Parallel checks #47

Open denisdefreyne opened 6 years ago

denisdefreyne commented 6 years ago

@fjan said:

My rather large site has a bunch of checks before being deployed: spell checker, link checker, assets checker, HTML validator, and several more which makes "nanoc check" a pretty long step in my workflow, much longer than the compile step most of the time.

I'd like to submit a feature request to run the checks in parallel, because they seem like a perfect candidate for it. I took a quick look at the code and I think it should be relatively easy since none of the checks changes any state. It would just need some work to use a thread-safe object for the error collection and the output of the check command would need rethinking to prevent it being interleaved. For example, checks could print a single dot to show they're doing something, (or if we want to do it really nice we could make each thread report a progress percentage to the parent).

Fjan commented 4 months ago

I'm using this patch in Checks.rb that does little more than adjust the loop to run each check in a separate thread, and a few formatting fixes. It works great.

class Nanoc::Checking::Runner
  ClassID = Struct.new(:identifier)
  def run_checks(classes)
    Nanoc::Core::Compiler.new_for(@site).run_until_reps_built
    puts "Starting checks…"
    length = classes.map { |c| c.identifier.to_s.length }.max + 10
    Parallel.map(classes) do |klass|
      check = klass.create(@site)
      check.run
      puts format("  %-#{length}s%s", "Check #{klass.identifier}: ",check.issues.empty? ? 'ok'.green : 'error'.red)
      check.issues.map!{Nanoc::Checking::Issue.new(_1.description,_1.subject,ClassID.new(klass.identifier))}
      check.issues
    end.reduce(:union)
  end
end

(edited to use parallel gem, because some parts of the check runner are not thread safe. This required me to replace class in the Issue with a Struct to allow it to serialize)