From ab9bd940d54f628fbbd48ea4a1c24f5816e4e371 Mon Sep 17 00:00:00 2001 From: sizief Date: Tue, 3 Feb 2026 16:38:10 +0100 Subject: [PATCH 1/2] set current company scope before enqueue --- app/models/data_drip/backfill_run.rb | 26 ++++++++++++---------- app/models/data_drip/backfill_run_batch.rb | 24 +++++++++++--------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/app/models/data_drip/backfill_run.rb b/app/models/data_drip/backfill_run.rb index 9f77340..5b47296 100644 --- a/app/models/data_drip/backfill_run.rb +++ b/app/models/data_drip/backfill_run.rb @@ -78,18 +78,20 @@ def backfill_class_properly_configured? errors.add(:backfill_class_name, "must inherit from DataDrip::Backfill") end - def validate_scope - return unless backfill_class_name.present? - return unless backfill_class - - begin - backfill = - backfill_class.new( - batch_size: batch_size || 100, - sleep_time: 5, - backfill_options: options || {} - ) - scope = backfill.scope + def validate_scope + return unless backfill_class_name.present? + return unless backfill_class + + begin + DataDrip.before_backfill&.call + + backfill = + backfill_class.new( + batch_size: batch_size || 100, + sleep_time: 5, + backfill_options: options || {} + ) + scope = backfill.scope scope = scope.limit(amount_of_elements) if amount_of_elements.present? && diff --git a/app/models/data_drip/backfill_run_batch.rb b/app/models/data_drip/backfill_run_batch.rb index a09acea..2ae798f 100644 --- a/app/models/data_drip/backfill_run_batch.rb +++ b/app/models/data_drip/backfill_run_batch.rb @@ -26,18 +26,20 @@ def enqueue enqueued! end - def run! - running! - migration = - backfill_run.backfill_class.new( - batch_size: batch_size, - sleep_time: 5, - backfill_options: backfill_run.options - ) + def run! + running! + DataDrip.before_backfill&.call - migration - .scope - .in_batches( + migration = + backfill_run.backfill_class.new( + batch_size: batch_size, + sleep_time: 5, + backfill_options: backfill_run.options + ) + + migration + .scope + .in_batches( of: batch_size, start: start_id, finish: finish_id From 94dabd47021e0d28c106ba2339844f44d5718469 Mon Sep 17 00:00:00 2001 From: sizief Date: Tue, 3 Feb 2026 16:48:37 +0100 Subject: [PATCH 2/2] specs --- .../data_drip/backfill_run_batch_spec.rb | 60 +++++++++++++++++++ spec/models/data_drip/backfill_run_spec.rb | 41 +++++++++++++ 2 files changed, 101 insertions(+) diff --git a/spec/models/data_drip/backfill_run_batch_spec.rb b/spec/models/data_drip/backfill_run_batch_spec.rb index b186815..22f4b84 100644 --- a/spec/models/data_drip/backfill_run_batch_spec.rb +++ b/spec/models/data_drip/backfill_run_batch_spec.rb @@ -10,6 +10,66 @@ let!(:employee4) { Employee.create!(name: "Alice", role: "manager", age: 25) } describe "#run!" do + describe "before_backfill callback" do + let(:backfill_run) do + backfill_run = + DataDrip::BackfillRun.new( + backfill_class_name: "AddRoleToEmployee", + batch_size: 10, + start_at: 1.hour.from_now, + backfiller: backfiller, + options: {} + ) + backfill_run.save!(validate: false) + backfill_run + end + + let(:batch) do + batch = + DataDrip::BackfillRunBatch.new( + backfill_run: backfill_run, + batch_size: 10, + start_id: employee1.id, + finish_id: employee3.id, + status: :pending + ) + batch.save!(validate: false) + batch.update_column(:status, 0) + batch + end + + it "calls DataDrip.before_backfill before processing" do + callback_called = false + original_callback = DataDrip.before_backfill + + DataDrip.before_backfill = -> { callback_called = true } + + batch.run! + + expect(callback_called).to be true + ensure + DataDrip.before_backfill = original_callback + end + + it "calls before_backfill before accessing scope" do + call_order = [] + original_callback = DataDrip.before_backfill + + DataDrip.before_backfill = -> { call_order << :before_backfill } + + allow_any_instance_of(AddRoleToEmployee).to receive(:scope).and_wrap_original do |original_method| + call_order << :scope_accessed + original_method.call + end + + batch.run! + + expect(call_order).to eq([:before_backfill, :scope_accessed]) + ensure + DataDrip.before_backfill = original_callback + end + end + let(:backfill_run) do # Skip validation to allow creation for testing backfill_run = diff --git a/spec/models/data_drip/backfill_run_spec.rb b/spec/models/data_drip/backfill_run_spec.rb index 848562b..c609fdb 100644 --- a/spec/models/data_drip/backfill_run_spec.rb +++ b/spec/models/data_drip/backfill_run_spec.rb @@ -18,6 +18,47 @@ end describe "validate_scope" do + describe "before_backfill callback" do + it "calls DataDrip.before_backfill during validation" do + callback_called = false + original_callback = DataDrip.before_backfill + + DataDrip.before_backfill = -> { callback_called = true } + + backfill_run = + DataDrip::BackfillRun.new( + valid_attributes.merge(options: { age: 25 }) + ) + backfill_run.valid? + + expect(callback_called).to be true + ensure + DataDrip.before_backfill = original_callback + end + + it "calls before_backfill before accessing scope" do + call_order = [] + original_callback = DataDrip.before_backfill + + DataDrip.before_backfill = -> { call_order << :before_backfill } + + allow_any_instance_of(AddRoleToEmployee).to receive(:scope).and_wrap_original do |original_method| + call_order << :scope_accessed + original_method.call + end + + backfill_run = + DataDrip::BackfillRun.new( + valid_attributes.merge(options: { age: 25 }) + ) + backfill_run.valid? + + expect(call_order).to eq([:before_backfill, :scope_accessed]) + ensure + DataDrip.before_backfill = original_callback + end + end + context "when scope has records" do it "is valid" do backfill_run =