Hintergrundjobs: DB-Model und allgemeine Modelimplementation mit ersten Test-Jobs
authorMoritz Bunkus <m.bunkus@linet-services.de>
Fri, 29 Oct 2010 13:42:14 +0000 (15:42 +0200)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Wed, 12 Jan 2011 10:13:49 +0000 (11:13 +0100)
SL/BackgroundJob/Base.pm [new file with mode: 0644]
SL/BackgroundJob/CleanBackgroundJobHistory.pm [new file with mode: 0644]
SL/BackgroundJob/Test.pm [new file with mode: 0644]
SL/DB/BackgroundJob.pm
SL/DB/Manager/BackgroundJob.pm

diff --git a/SL/BackgroundJob/Base.pm b/SL/BackgroundJob/Base.pm
new file mode 100644 (file)
index 0000000..44702d8
--- /dev/null
@@ -0,0 +1,31 @@
+package SL::BackgroundJob::Base;
+
+use strict;
+
+use parent qw(Rose::Object);
+
+use SL::DB::BackgroundJob;
+
+sub create_standard_job {
+  my $self_or_class = shift;
+  my $cron_spec     = shift;
+
+  my $package       = ref($self_or_class) || $self_or_class;
+  $package          =~ s/SL::BackgroundJob:://;
+
+  my %params        = (cron_spec    => $cron_spec || '* * * * *',
+                       type         => 'interval',
+                       active       => 1,
+                       package_name => $package);
+
+  my $job = SL::DB::Manager::BackgroundJob->find_by(package_name => $params{package_name});
+  if (!$job) {
+    $job = SL::DB::BackgroundJob->new(%params)->update_next_run_at;
+  } else {
+    $job->assign_attributes(%params)->update_next_run_at;
+  }
+
+  return $job;
+}
+
+1;
diff --git a/SL/BackgroundJob/CleanBackgroundJobHistory.pm b/SL/BackgroundJob/CleanBackgroundJobHistory.pm
new file mode 100644 (file)
index 0000000..117a4d4
--- /dev/null
@@ -0,0 +1,29 @@
+package SL::BackgroundJob::CleanBackgroundJobHistory;
+
+use parent qw(SL::BackgroundJob::Base);
+
+use SL::DB::BackgroundJobHistory;
+
+sub create_job {
+  $_[0]->create_standard_job('0 3 * * *'); # daily at 3:00 am
+}
+
+sub run {
+  my $self    = shift;
+  my $db_obj  = shift;
+
+  my $options = $db_obj->data_as_hash;
+  $options->{retention_success} ||= 14;
+  $options->{retention_failure} ||= 3 * 30;
+
+  my $today = DateTime->today_local;
+
+  for my $status (qw(success failure)) {
+    SL::DB::Manager::BackgroundJobHistory->delete_all(where =>  [ status => $status,
+                                                                  run_at => { lt => $today->clone->subtract(days => $options->{"retention_${status}"}) } ]);
+  }
+
+  return 1;
+}
+
+1;
diff --git a/SL/BackgroundJob/Test.pm b/SL/BackgroundJob/Test.pm
new file mode 100644 (file)
index 0000000..01c8569
--- /dev/null
@@ -0,0 +1,13 @@
+package SL::BackgroundJob::Test;
+
+use parent qw(SL::BackgroundJob::Base);
+
+sub run {
+  my $self   = shift;
+  my $db_obj = shift;
+
+  $::lxdebug->message(0, "Test job is being executed.");
+}
+
+
+1;
index f4edf2d..b9e00c4 100644 (file)
@@ -3,16 +3,65 @@ package SL::DB::BackgroundJob;
 use strict;
 
 use DateTime::Event::Cron;
+use English qw(-no_match_vars);
 
 use SL::DB::MetaSetup::BackgroundJob;
 use SL::DB::Manager::BackgroundJob;
 
+use SL::DB::BackgroundJobHistory;
+
+use SL::BackgroundJob::Test;
+
 sub update_next_run_at {
   my $self = shift;
 
   my $cron = DateTime::Event::Cron->new_from_cron($self->cron_spec || '* * * * *');
-  $self->update_attributes(next_run_at => $cron->next->set_time_zone($::locale->get_local_time_zone));
+  $self->update_attributes(next_run_at => $cron->next(DateTime->now_local));
   return $self;
 }
 
+sub run {
+  my $self = shift;
+
+  my $package = "SL::BackgroundJob::" . $self->package_name;
+  my $run_at  = DateTime->now_local;
+  my $history;
+
+  eval {
+    my $result = $package->new->run($self);
+
+    $history = SL::DB::BackgroundJobHistory
+      ->new(package_name => $self->package_name,
+            run_at       => $run_at,
+            status       => 'success',
+            result       => $result,
+            data         => $self->data);
+    $history->save;
+
+    1;
+  };
+
+  if ($EVAL_ERROR) {
+    $history = SL::DB::BackgroundJobHistory
+      ->new(package_name => $self->package_name,
+            run_at       => $run_at,
+            status       => 'failure',
+            error        => $EVAL_ERROR,
+            data         => $self->data);
+    $history->save;
+  }
+
+  $self->assign_attributes(last_run_at => $run_at)->update_next_run_at;
+
+  return $history;
+}
+
+sub data_as_hash {
+  my $self = shift;
+  return {}                        if !$self->data;
+  return $self->data               if ref($self->{data}) eq 'HASH';
+  return YAML::Load($self->{data}) if !ref($self->{data});
+  return {};
+}
+
 1;
index 178f9d3..35a773d 100644 (file)
@@ -15,8 +15,21 @@ sub cleanup {
 }
 
 sub get_all_need_to_run {
-  my $class = shift;
-  return $class->get_all(where => [ and => [ active => 1, next_run_at => { le => DateTime->now_local } ] ]);
+  my $class         = shift;
+
+  my $now           = DateTime->now_local;
+  my @interval_args = (and => [ type        => 'interval',
+                                active      => 1,
+                                next_run_at => { le => $now } ]);
+  my @once_args     = (and => [ type        => 'once',
+                                active      => 1,
+                                last_run_at => undef,
+                                or          => [ cron_spec   => undef,
+                                                 cron_spec   => '',
+                                                 next_run_at => undef,
+                                                 next_run_at => { le => $now } ] ]);
+
+  return $class->get_all(where => [ or => [ @interval_args, @once_args ] ]);
 }
 
 1;