discourse/migrations/spec/lib/converters/base/worker_spec.rb
Gerhard Schlager 7c3a29c9d6
DEV: Add converter framework for migrations-tooling (#28540)
* Updates GitHub Actions
* Switches from `bundler/inline` to an optional group in the `Gemfile` because the previous solution didn't work well with rspec
* Adds the converter framework and tests
* Allows loading private converters (see README)
* Switches from multiple CLI tools to a single CLI
* Makes DB connections reusable and adds a new abstraction for the `IntermediateDB`
* `IntermediateDB` acts as an interface for IPC calls when a converter steps runs in parallel (forks). Only the main process writes to the DB.
* Includes a simple example implementation of a converter for now.
2024-09-09 17:14:39 +02:00

115 lines
3.1 KiB
Ruby

# frozen_string_literal: true
RSpec.describe ::Migrations::Converters::Base::Worker do
subject(:worker) { described_class.new(index, input_queue, output_queue, job) }
let(:index) { 1 }
let(:input_queue) { Queue.new }
let(:output_queue) { Queue.new }
let(:job) do
instance_double(::Migrations::Converters::Base::ParallelJob, run: "result", cleanup: nil)
end
after do
input_queue.close if !input_queue.closed?
output_queue.close if !output_queue.closed?
end
describe "#start" do
it "works when `input_queue` is empty" do
expect do
worker.start
input_queue.close
worker.wait
output_queue.close
end.not_to raise_error
end
it "uses `ForkManager.fork`" do
allow(::Migrations::ForkManager).to receive(:fork).and_call_original
worker.start
input_queue.close
worker.wait
output_queue.close
expect(::Migrations::ForkManager).to have_received(:fork)
end
it "writes the output of `job.run` into `output_queue`" do
allow(job).to receive(:run) { |data| "run: #{data[:text]}" }
worker.start
input_queue << { text: "Item 1" } << { text: "Item 2" } << { text: "Item 3" }
input_queue.close
worker.wait
output_queue.close
expect(output_queue).to have_queue_contents("run: Item 1", "run: Item 2", "run: Item 3")
end
def create_progress_stats(progress: 1, warning_count: 0, error_count: 0)
stats = ::Migrations::Converters::Base::ProgressStats.new
stats.progress = progress
stats.warning_count = warning_count
stats.error_count = error_count
stats
end
it "writes objects to the `output_queue`" do
all_stats = [
create_progress_stats,
create_progress_stats(warning_count: 1),
create_progress_stats(warning_count: 1, error_count: 1),
create_progress_stats(warning_count: 2, error_count: 1),
]
allow(job).to receive(:run) do |data|
index = data[:index]
[index, all_stats[index]]
end
worker.start
input_queue << { index: 0 } << { index: 1 } << { index: 2 } << { index: 3 }
input_queue.close
worker.wait
output_queue.close
expect(output_queue).to have_queue_contents(
[0, all_stats[0]],
[1, all_stats[1]],
[2, all_stats[2]],
[3, all_stats[3]],
)
end
it "runs `job.cleanup` at the end" do
temp_file = Tempfile.new("method_call_check")
temp_file_path = temp_file.path
allow(job).to receive(:run) do |data|
File.write(temp_file_path, "run: #{data[:text]}\n", mode: "a+")
data[:text]
end
allow(job).to receive(:cleanup) do
File.write(temp_file_path, "cleanup\n", mode: "a+")
end
worker.start
input_queue << { text: "Item 1" } << { text: "Item 2" } << { text: "Item 3" }
input_queue.close
worker.wait
output_queue.close
expect(File.read(temp_file_path)).to eq <<~LOG
run: Item 1
run: Item 2
run: Item 3
cleanup
LOG
ensure
temp_file.unlink
end
end
end