pj migration: retry when changing the content type fails

This commit is contained in:
Pierre de La Morinerie 2019-07-16 17:51:29 +02:00
parent fa2d6f7b8b
commit 80efe27ff2
2 changed files with 38 additions and 1 deletions

View file

@ -154,10 +154,20 @@ class CarrierwaveActiveStorageMigrationService
attachment attachment
end end
def fix_content_type(blob) def fix_content_type(blob, retry_delay: 5)
retries ||= 0
# In OpenStack, ActiveStorage cannot inject the MIME type on the fly during direct # In OpenStack, ActiveStorage cannot inject the MIME type on the fly during direct
# download. Instead, the MIME type needs to be stored statically on the file object # download. Instead, the MIME type needs to be stored statically on the file object
# in OpenStack. This is what this call does. # in OpenStack. This is what this call does.
blob.service.change_content_type(blob.key, blob.content_type) blob.service.change_content_type(blob.key, blob.content_type)
rescue
# When we quickly create a new attachment, and then change its content type,
# the Object Storage may not be synchronized yet. It this cas, it will return a
# "409 Conflict" error.
#
# Wait for a while, then try again twice (before giving up).
sleep(retry_delay)
retry if (retries += 1) < 3
raise
end end
end end

View file

@ -69,4 +69,31 @@ describe CarrierwaveActiveStorageMigrationService do
end end
end end
end end
describe '.fix_content_type' do
let(:pj) { create(:piece_justificative, :rib, updated_at: Time.zone.local(2019, 01, 01, 12, 00)) }
let(:blob) { service.make_empty_blob(pj.content, pj.updated_at.iso8601, filename: pj.original_filename) }
context 'when the request is ok' do
it 'succeeds' do
expect(blob.service).to receive(:change_content_type).and_return(true)
expect { service.fix_content_type(blob) }.not_to raise_error
end
end
context 'when the request fails initially' do
it 'retries the request' do
expect(blob.service).to receive(:change_content_type).and_raise(StandardError).ordered
expect(blob.service).to receive(:change_content_type).and_return(true).ordered
expect { service.fix_content_type(blob, retry_delay: 0.01) }.not_to raise_error
end
end
context 'when the request fails too many times' do
it 'gives up' do
expect(blob.service).to receive(:change_content_type).and_raise(StandardError).thrice
expect { service.fix_content_type(blob, retry_delay: 0.01) }.to raise_error(StandardError)
end
end
end
end end