Class: WickedPdf::Command

Inherits:
Object
  • Object
show all
Defined in:
lib/wicked_pdf/command.rb

Defined Under Namespace

Classes: BatchJob

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(binary: Binary.default, option_parser: OptionParser.new) ⇒ Command

Returns a new instance of Command.



5
6
7
8
# File 'lib/wicked_pdf/command.rb', line 5

def initialize(binary: Binary.default, option_parser: OptionParser.new)
  @binary = binary
  @option_parser = option_parser
end

Instance Attribute Details

#binaryObject (readonly)

Returns the value of attribute binary.



3
4
5
# File 'lib/wicked_pdf/command.rb', line 3

def binary
  @binary
end

#option_parserObject (readonly)

Returns the value of attribute option_parser.



3
4
5
# File 'lib/wicked_pdf/command.rb', line 3

def option_parser
  @option_parser
end

Instance Method Details

#execute(options, *args) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/wicked_pdf/command.rb', line 10

def execute(options, *args)
  command = [binary.path]
  command += global_argv
  command += option_parser.parse(options)
  command += args

  print_command(command.inspect) if in_development_mode?

  if track_progress?(options)
    Progress.new(options[:progress]).execute(command)
  else
    err = run_process(command)

    raise GenerationError, "Error generating PDF\n Command Error: #{err}" if options[:raise_on_all_errors] && !err.empty?

    err
  end
end

#execute_batch(jobs, concurrency: 1) ⇒ Object

Runs several conversions through shared wkhtmltopdf processes using --read-args-from-stdin, avoiding one process boot per document.

Each job is a Hash with:

options:     wkhtmltopdf options for this conversion only
url:         input URL (file:///... for local files)
output_path: file the PDF is written to

Jobs are split into concurrency contiguous slices, each processed by its own wkhtmltopdf process. wkhtmltopdf aborts a batch at the first failing conversion, so the failed job is retried as a normal single invocation (for a proper error) and the batch resumed with the rest. Raises WickedPdf::GenerationError if a job cannot be rendered.

All argv compilation happens here on the calling thread: OptionParser is not thread-safe (it accumulates tempfile state for inline header/footer content), so worker threads only ever see frozen strings.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/wicked_pdf/command.rb', line 46

def execute_batch(jobs, concurrency: 1)
  return if jobs.empty?

  compiled = jobs.map { |job| BatchJob.new(job, batch_argv(job)) }

  slices = compiled.each_slice(batch_slice_size(jobs.size, concurrency)).to_a
  errors = Array.new(slices.size)

  slices.each_with_index.map do |slice, index|
    Thread.new do
      process_batch_slice(slice)
    rescue StandardError => e
      errors[index] = e
    end
  end.each(&:join)

  error = errors.compact.first
  raise error if error
end