Merge pull request #7629 from betagouv/fix-exports
Fix: purge stuck exports & archives
This commit is contained in:
commit
40a7b4a025
8 changed files with 40 additions and 13 deletions
|
@ -11,7 +11,7 @@ class ArchiveDashboard < Administrate::BaseDashboard
|
||||||
id: Field::Number,
|
id: Field::Number,
|
||||||
created_at: Field::DateTime,
|
created_at: Field::DateTime,
|
||||||
updated_at: Field::DateTime,
|
updated_at: Field::DateTime,
|
||||||
status: Field::String,
|
job_status: Field::String,
|
||||||
file: AttachmentField
|
file: AttachmentField
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ class ArchiveDashboard < Administrate::BaseDashboard
|
||||||
:id,
|
:id,
|
||||||
:created_at,
|
:created_at,
|
||||||
:updated_at,
|
:updated_at,
|
||||||
:status,
|
:job_status,
|
||||||
:file
|
:file
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
|
@ -34,6 +34,6 @@ class ArchiveDashboard < Administrate::BaseDashboard
|
||||||
:id,
|
:id,
|
||||||
:created_at,
|
:created_at,
|
||||||
:updated_at,
|
:updated_at,
|
||||||
:status
|
:job_status
|
||||||
].freeze
|
].freeze
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,5 +3,6 @@ class Cron::PurgeStaleArchivesJob < Cron::CronJob
|
||||||
|
|
||||||
def perform
|
def perform
|
||||||
Archive.stale(Archive::RETENTION_DURATION).destroy_all
|
Archive.stale(Archive::RETENTION_DURATION).destroy_all
|
||||||
|
Archive.stuck(Archive::MAX_DUREE_GENERATION).destroy_all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,5 +3,6 @@ class Cron::PurgeStaleExportsJob < Cron::CronJob
|
||||||
|
|
||||||
def perform
|
def perform
|
||||||
Export.stale(Export::MAX_DUREE_CONSERVATION_EXPORT).destroy_all
|
Export.stale(Export::MAX_DUREE_CONSERVATION_EXPORT).destroy_all
|
||||||
|
Export.stuck(Export::MAX_DUREE_GENERATION).destroy_all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Archive < ApplicationRecord
|
||||||
include TransientModelsWithPurgeableJobConcern
|
include TransientModelsWithPurgeableJobConcern
|
||||||
|
|
||||||
RETENTION_DURATION = 4.days
|
RETENTION_DURATION = 4.days
|
||||||
|
MAX_DUREE_GENERATION = 24.hours
|
||||||
MAX_SIZE = 100.gigabytes
|
MAX_SIZE = 100.gigabytes
|
||||||
|
|
||||||
has_and_belongs_to_many :groupe_instructeurs
|
has_and_belongs_to_many :groupe_instructeurs
|
||||||
|
|
|
@ -35,6 +35,11 @@ module TransientModelsWithPurgeableJobConcern
|
||||||
.where('updated_at < ?', (Time.zone.now - duration))
|
.where('updated_at < ?', (Time.zone.now - duration))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scope :stuck, lambda { |duration|
|
||||||
|
where(job_status: [job_statuses.fetch(:pending)])
|
||||||
|
.where('updated_at < ?', (Time.zone.now - duration))
|
||||||
|
}
|
||||||
|
|
||||||
def available?
|
def available?
|
||||||
generated?
|
generated?
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,6 +17,7 @@ class Export < ApplicationRecord
|
||||||
include TransientModelsWithPurgeableJobConcern
|
include TransientModelsWithPurgeableJobConcern
|
||||||
|
|
||||||
MAX_DUREE_CONSERVATION_EXPORT = 16.hours
|
MAX_DUREE_CONSERVATION_EXPORT = 16.hours
|
||||||
|
MAX_DUREE_GENERATION = 12.hours
|
||||||
|
|
||||||
enum format: {
|
enum format: {
|
||||||
csv: 'csv',
|
csv: 'csv',
|
||||||
|
|
|
@ -4,26 +4,34 @@ describe Archive do
|
||||||
before { Timecop.freeze(Time.zone.now) }
|
before { Timecop.freeze(Time.zone.now) }
|
||||||
after { Timecop.return }
|
after { Timecop.return }
|
||||||
|
|
||||||
let(:archive) { create(:archive, job_status: :pending) }
|
let!(:archive) { create(:archive, job_status: :pending) }
|
||||||
|
|
||||||
describe 'scopes' do
|
describe 'scopes' do
|
||||||
describe 'staled' do
|
describe 'staled' do
|
||||||
let(:recent_archive) { create(:archive, job_status: :pending) }
|
let!(:recent_archive) { create(:archive, job_status: :pending) }
|
||||||
let(:staled_archive_still_pending) { create(:archive, job_status: :pending, updated_at: (Archive::RETENTION_DURATION + 2).days.ago) }
|
let!(:staled_archive_still_pending) { create(:archive, job_status: :pending, updated_at: (Archive::RETENTION_DURATION + 2).days.ago) }
|
||||||
let(:staled_archive_still_failed) { create(:archive, job_status: :failed, updated_at: (Archive::RETENTION_DURATION + 2).days.ago) }
|
let!(:staled_archive_still_failed) { create(:archive, job_status: :failed, updated_at: (Archive::RETENTION_DURATION + 2).days.ago) }
|
||||||
let(:staled_archive_still_generated) { create(:archive, job_status: :generated, updated_at: (Archive::RETENTION_DURATION + 2).days.ago) }
|
let!(:staled_archive_still_generated) { create(:archive, job_status: :generated, updated_at: (Archive::RETENTION_DURATION + 2).days.ago) }
|
||||||
|
|
||||||
subject do
|
subject do
|
||||||
archive
|
|
||||||
recent_archive
|
|
||||||
staled_archive_still_pending
|
|
||||||
staled_archive_still_failed
|
|
||||||
staled_archive_still_generated
|
|
||||||
Archive.stale(Archive::RETENTION_DURATION)
|
Archive.stale(Archive::RETENTION_DURATION)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to match_array([staled_archive_still_failed, staled_archive_still_generated]) }
|
it { is_expected.to match_array([staled_archive_still_failed, staled_archive_still_generated]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'stuck' do
|
||||||
|
let!(:recent_archive) { create(:archive, job_status: :pending) }
|
||||||
|
let!(:staled_archive_still_pending) { create(:archive, job_status: :pending, updated_at: (Archive::MAX_DUREE_GENERATION + 2).days.ago) }
|
||||||
|
let!(:staled_archive_still_failed) { create(:archive, job_status: :failed, updated_at: (Archive::MAX_DUREE_GENERATION + 2).days.ago) }
|
||||||
|
let!(:staled_archive_still_generated) { create(:archive, job_status: :generated, updated_at: (Archive::MAX_DUREE_GENERATION + 2).days.ago) }
|
||||||
|
|
||||||
|
subject do
|
||||||
|
Archive.stuck(Archive::MAX_DUREE_GENERATION)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to match_array([staled_archive_still_pending]) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.job_status' do
|
describe '.job_status' do
|
||||||
|
|
|
@ -31,6 +31,16 @@ RSpec.describe Export, type: :model do
|
||||||
it { expect(Export.stale(Export::MAX_DUREE_CONSERVATION_EXPORT)).to match_array([stale_export_generated, stale_export_failed]) }
|
it { expect(Export.stale(Export::MAX_DUREE_CONSERVATION_EXPORT)).to match_array([stale_export_generated, stale_export_failed]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '.stuck' do
|
||||||
|
let!(:export) { create(:export) }
|
||||||
|
let(:stuck_date) { Time.zone.now() - (Export::MAX_DUREE_GENERATION + 1.minute) }
|
||||||
|
let!(:stale_export_generated) { create(:export, :generated, updated_at: stuck_date) }
|
||||||
|
let!(:stale_export_failed) { create(:export, :failed, updated_at: stuck_date) }
|
||||||
|
let!(:stale_export_pending) { create(:export, :pending, updated_at: stuck_date) }
|
||||||
|
|
||||||
|
it { expect(Export.stuck(Export::MAX_DUREE_GENERATION)).to match_array([stale_export_pending]) }
|
||||||
|
end
|
||||||
|
|
||||||
describe '.destroy' do
|
describe '.destroy' do
|
||||||
let!(:groupe_instructeur) { create(:groupe_instructeur) }
|
let!(:groupe_instructeur) { create(:groupe_instructeur) }
|
||||||
let!(:export) { create(:export, groupe_instructeurs: [groupe_instructeur]) }
|
let!(:export) { create(:export, groupe_instructeurs: [groupe_instructeur]) }
|
||||||
|
|
Loading…
Add table
Reference in a new issue