From 6a43fd5b5ab34ab56c5b474ffcd67651a248854c Mon Sep 17 00:00:00 2001 From: Sony Mathew <2040199+sony-mathew@users.noreply.github.com> Date: Wed, 22 Jul 2026 23:59:30 +0530 Subject: [PATCH] fix(imports): lock stalled import retries --- .../data_imports/intercom/retry_service.rb | 15 ++++++++------- .../data_imports/intercom/retry_service_spec.rb | 13 +++++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/app/services/data_imports/intercom/retry_service.rb b/app/services/data_imports/intercom/retry_service.rb index 6d0cb5c9d..57289d917 100644 --- a/app/services/data_imports/intercom/retry_service.rb +++ b/app/services/data_imports/intercom/retry_service.rb @@ -8,14 +8,15 @@ class DataImports::Intercom::RetryService def perform @account.with_lock do - @data_import.reload - next :not_stalled unless @data_import.stalled? - next :active_import_exists if another_active_import? - next :access_token_missing if @data_import.access_token.blank? + @data_import.with_lock do + next :not_stalled unless @data_import.stalled? + next :active_import_exists if another_active_import? + next :access_token_missing if @data_import.access_token.blank? - @data_import.assign_active_intercom_import_run_id - @data_import.update!(status: :pending) - :enqueue + @data_import.assign_active_intercom_import_run_id + @data_import.update!(status: :pending) + :enqueue + end end end diff --git a/spec/services/data_imports/intercom/retry_service_spec.rb b/spec/services/data_imports/intercom/retry_service_spec.rb index f94283993..7c6ccc6ea 100644 --- a/spec/services/data_imports/intercom/retry_service_spec.rb +++ b/spec/services/data_imports/intercom/retry_service_spec.rb @@ -38,6 +38,19 @@ RSpec.describe DataImports::Intercom::RetryService do expect(data_import.reload).to be_processing end + it 'rechecks the import state after acquiring its row lock' do + data_import.update!(updated_at: 16.minutes.ago) + allow(data_import).to receive(:with_lock).and_wrap_original do |method, *args, &block| + data_import.update!(status: :completed, completed_at: Time.current) + method.call(*args, &block) + end + + result = described_class.new(account: account, data_import: data_import).perform + + expect(result).to eq(:not_stalled) + expect(data_import.reload).to be_completed + end + it 'does not retry while another Intercom import is active' do data_import.update!(updated_at: 16.minutes.ago) create(:data_import, :intercom, account: account, status: :processing)