Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,28 @@ module QueuedSpatialProcessing
extend ActiveSupport::Concern
mattr_accessor :priority_offset, default: 0 # Offsets the queued priority of spatial tasks. Lower numbers run with higher priority

class_methods do
# Records whose most recent feature import failed. `->>` yields NULL for a missing
# key, so a record that has never been imported is not included.
def with_failed_feature_updates
where("spatial_processing_status_cache->>'update_features!' = 'failure'")
end

# Re-import everything whose last attempt failed. Nothing else retries these, so a
# record broken by a defect stays broken after the defect is fixed unless something
# sweeps it up.
#
# Queued rather than run inline, so a caller (a deploy migration, a console) doesn't
# block on reimporting shapefiles, and so `SpatialProcessingJob`'s callbacks maintain
# `spatial_processing_status_cache` — calling `#update_features!` directly bypasses
# them and leaves a record flagged as failed even when the retry succeeded.
def retry_failed_feature_updates!(**options)
with_failed_feature_updates.find_each do |record|
record.delay_update_features!(**options)
end
end
end

def self.update_cached_status(record, method_name, state)
return unless record.has_attribute?(:spatial_processing_status_cache)

Expand Down
2 changes: 1 addition & 1 deletion lib/spatial_features/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module SpatialFeatures
VERSION = "3.11.0"
VERSION = "3.11.1"
end
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,37 @@
end
end

describe '::retry_failed_feature_updates!', delayed_job: false do
let(:klass) { new_dummy_class(:spatial_processing_status_cache => :jsonb) }

def status!(record, state)
SpatialFeatures::QueuedSpatialProcessing.update_cached_status(record, 'update_features!', state)
end

it 'queues a feature update for each record whose last import failed' do
failed = klass.create.tap {|record| status!(record, 'failure') }

expect { klass.retry_failed_feature_updates! }
.to change { failed.spatial_processing_jobs('update_features!').count }
.by(1)
end

it 'ignores records that succeeded, and records never imported at all' do
klass.create.tap {|record| status!(record, 'success') }
klass.create # no import attempted, so no key in the cache at all

expect { klass.retry_failed_feature_updates! }.not_to change { Delayed::Job.count }
end

it 'passes options through to the queued job' do
klass.create.tap {|record| status!(record, 'failure') }

klass.retry_failed_feature_updates!(:priority => 10)

expect(Delayed::Job.last.priority).to eq(10)
end
end

describe '#clear_feature_update_error_status' do
let(:klass) { new_dummy_class(:spatial_processing_status_cache => :jsonb) }

Expand Down