From c81d27de083f3be0df0dfd4b2293a6648df5b2e3 Mon Sep 17 00:00:00 2001 From: Nick Clemens Date: Fri, 22 May 2026 14:25:23 +0000 Subject: [PATCH] Bug 35948: Add jobs_unfinished_days and jobs_unfinished_type to cleanup_database.pl This patch adds two new parameters to control the deletion of background jobs that did not complete. Some libraries may want to keep a failed job longer than a completed one for debugging reasons. To test: 0 - Apply patch 1 - Make some old failed jobs: INSERT INTO background_jobs (status,type,enqueued_on) VALUES ('started','update_elastic_index','2020-01-01'), ('failed','update_elastic_index','2026-01-01'), ('started','other_type','2021-01-01'), ('failed','other_type','2026-01-01'); 2 - Confirm defaults of 365 and update_elastic_index for new params: perl misc/cronjobs/cleanup_database.pl -v --jobs-unfinished-days 3 - Should indicate 1 job older than 365 of type update_elastic_index would have been deleted 4 - Confirm days param works perl misc/cronjobs/cleanup_database.pl -v --jobs-unfinished-days 30 5 - Shoudl find 2 elastic jobs 6 - Confirm type param perl misc/cronjobs/cleanup_database.pl -v --jobs-unfinished-days --jobs-unfinished-type=other_type 7 - Should find 1 8 - Confirm type and days perl misc/cronjobs/cleanup_database.pl -v --jobs-unfinished-days 30 --jobs-unfinished-type=other_type 9 - Should find 2 10 - Confirm repeated type perl misc/cronjobs/cleanup_database.pl -v --jobs-unfinished-days=30 --jobs-unfinished-type=other_type --jobs-unfinished-type=update_elastic_index 11 - Finds 4 12 - Confirm deletion perl misc/cronjobs/cleanup_database.pl -v --jobs-unfinished-days=30 --jobs-unfinished-type=other_type --jobs-unfinished-type=update_elastic_index --confirm 13 - All your made up jobs are removed Signed-off-by: Trevor Diamond Signed-off-by: Martin Renvoize Signed-off-by: Pedro Amorim --- misc/cronjobs/cleanup_database.pl | 61 +++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/misc/cronjobs/cleanup_database.pl b/misc/cronjobs/cleanup_database.pl index 32f80f6888..d3c50654bd 100755 --- a/misc/cronjobs/cleanup_database.pl +++ b/misc/cronjobs/cleanup_database.pl @@ -29,6 +29,8 @@ use constant DEFAULT_SHARE_INVITATION_EXPIRY_DAYS => 14; use constant DEFAULT_DEBARMENTS_PURGEDAYS => 30; use constant DEFAULT_JOBS_PURGEDAYS => 1; use constant DEFAULT_JOBS_PURGETYPES => qw{ update_elastic_index }; +use constant DEFAULT_JOBS_UNFINISHED_PURGEDAYS => 365; +use constant DEFAULT_JOBS_UNFINISHED_PURGETYPES => qw{ update_elastic_index }; use constant DEFAULT_EDIFACT_MSG_PURGEDAYS => 365; use Getopt::Long qw( GetOptions ); @@ -124,6 +126,9 @@ Usage: $0 --cards DAY Purge card creator batches last added to more than DAYS days ago. --return-claims Purge all resolved return claims older than the number of days specified in the system preference CleanUpDatabaseReturnClaims. + --jobs-unfinished-days DAYS Purge all unfinished background jobs this many days old. Defaults to 365 if no DAYS provided. + --jobs-unfinished-type TYPES What type of unfinished background jobs to purge. Defaults to "update_elastic_index" if omitted + Specifying "all" will purge all types. Repeatable. --jobs-days DAYS Purge all finished background jobs this many days old. Defaults to 1 if no DAYS provided. --jobs-type TYPES What type of background job to purge. Defaults to "update_elastic_index" if omitted Specifying "all" will purge all types. Repeatable. @@ -174,6 +179,8 @@ my $cards; my @log_modules; my @preserve_logs; my @log_actions; +my $jobs_unfinished_days; +my @jobs_unfinished_types; my $jobs_days; my @jobs_types; my $reports; @@ -224,6 +231,8 @@ GetOptions( 'labels:i' => \$labels, 'cards:i' => \$cards, 'return-claims' => \$return_claims, + 'jobs-unfinished-type:s' => \@jobs_unfinished_types, + 'jobs-unfinished-days:i' => \$jobs_unfinished_days, 'jobs-type:s' => \@jobs_types, 'jobs-days:i' => \$jobs_days, 'reports:i' => \$reports, @@ -231,17 +240,20 @@ GetOptions( ) || usage(1); # Use default values -$sessions = 1 if $sess_days && $sess_days > 0; -$pImport = DEFAULT_IMPORT_PURGEDAYS if defined($pImport) && $pImport == 0; -$pLogs = DEFAULT_LOGS_PURGEDAYS if defined($pLogs) && $pLogs == 0; -$zebraqueue_days = DEFAULT_ZEBRAQ_PURGEDAYS if defined($zebraqueue_days) && $zebraqueue_days == 0; -$mail = DEFAULT_MAIL_PURGEDAYS if defined($mail) && $mail == 0; -$pSearchhistory = DEFAULT_SEARCHHISTORY_PURGEDAYS if defined($pSearchhistory) && $pSearchhistory == 0; -$pDebarments = DEFAULT_DEBARMENTS_PURGEDAYS if defined($pDebarments) && $pDebarments == 0; -$pMessages = DEFAULT_MESSAGES_PURGEDAYS if defined($pMessages) && $pMessages == 0; -$jobs_days = DEFAULT_JOBS_PURGEDAYS if defined($jobs_days) && $jobs_days == 0; -@jobs_types = (DEFAULT_JOBS_PURGETYPES) if $jobs_days && @jobs_types == 0; -$edifact_msg_days = DEFAULT_EDIFACT_MSG_PURGEDAYS if defined($edifact_msg_days) && $edifact_msg_days == 0; +$sessions = 1 if $sess_days && $sess_days > 0; +$pImport = DEFAULT_IMPORT_PURGEDAYS if defined($pImport) && $pImport == 0; +$pLogs = DEFAULT_LOGS_PURGEDAYS if defined($pLogs) && $pLogs == 0; +$zebraqueue_days = DEFAULT_ZEBRAQ_PURGEDAYS if defined($zebraqueue_days) && $zebraqueue_days == 0; +$mail = DEFAULT_MAIL_PURGEDAYS if defined($mail) && $mail == 0; +$pSearchhistory = DEFAULT_SEARCHHISTORY_PURGEDAYS if defined($pSearchhistory) && $pSearchhistory == 0; +$pDebarments = DEFAULT_DEBARMENTS_PURGEDAYS if defined($pDebarments) && $pDebarments == 0; +$pMessages = DEFAULT_MESSAGES_PURGEDAYS if defined($pMessages) && $pMessages == 0; +$jobs_unfinished_days = DEFAULT_JOBS_UNFINISHED_PURGEDAYS + if defined($jobs_unfinished_days) && $jobs_unfinished_days == 0; +@jobs_unfinished_types = (DEFAULT_JOBS_UNFINISHED_PURGETYPES) if $jobs_unfinished_days && @jobs_unfinished_types == 0; +$jobs_days = DEFAULT_JOBS_PURGEDAYS if defined($jobs_days) && $jobs_days == 0; +@jobs_types = (DEFAULT_JOBS_PURGETYPES) if $jobs_days && @jobs_types == 0; +$edifact_msg_days = DEFAULT_EDIFACT_MSG_PURGEDAYS if defined($edifact_msg_days) && $edifact_msg_days == 0; @statistics_types = ( @statistics_types, @Koha::Statistic::pseudonymization_types ) if defined($statistics_type_pseudo); @statistics_types = keys %{ { map { $_, 1 } @statistics_types } }; # remove duplicate types @@ -295,6 +307,7 @@ unless ( $sessions || $cards || $return_claims || $jobs_days + || $jobs_unfinished_days || $reports || $edifact_msg_days ) { @@ -780,6 +793,32 @@ if ($cards) { } } +if ($jobs_unfinished_days) { + print "Purging unfinished background jobs more than $jobs_unfinished_days days ago.\n" + if $verbose; + my $jobs = Koha::BackgroundJobs->search( + { + status => { '!=' => 'finished' }, + ( $jobs_unfinished_types[0] eq 'all' ? () : ( type => \@jobs_unfinished_types ) ) + } + )->filter_by_last_update( + { + timestamp_column_name => 'enqueued_on', + days => $jobs_unfinished_days, + } + ); + my $count = $jobs->count; + $jobs->delete if $confirm; + if ($verbose) { + say $confirm + ? sprintf "Done with purging unfinished %d background jobs of type(s): %s added more than %d days ago.\n", + $count, join( ',', @jobs_unfinished_types ), $jobs_unfinished_days + : sprintf + "%d unfinished background jobs of type(s): %s added more than %d days ago would have been purged.", + $count, join( ',', @jobs_unfinished_types ), $jobs_unfinished_days; + } +} + if ($jobs_days) { print "Purging background jobs more than $jobs_days days ago.\n" if $verbose;