compare timestamps rathr than DateTime objects, it's easier to debug that way
Jos Boumans [Tue, 28 Nov 2006 12:09:29 +0000 (12:09 +0000)]
keep a local cache to see when the 'next run time' is when there was no 'last run time'

lib/Catalyst/Plugin/Scheduler/Base.pm
lib/Catalyst/Plugin/Scheduler/Event.pm

index 6b2f571..1a56b72 100755 (executable)
@@ -112,7 +112,7 @@ sub list_pending_events {
     
     ### there are no events scheduled?
     my @events  = $self->list_events or return;
-    my $now     = DateTime->now( time_zone => $tz );
+    my $now     = DateTime->now( time_zone => $tz )->epoch;
     
     ### list of pending events
     my @pending;
@@ -139,7 +139,7 @@ sub list_pending_events {
         ### we're due according to our cron-entry...
         if( $event->set ) {
             ### is the next run time now, or even before now?
-            push @pending, $event if $event->next_run_as_dt <= $now;
+            push @pending, $event if $event->next_run <= $now;
         }
     }
 
index 92ae788..76a96f7 100755 (executable)
@@ -258,17 +258,39 @@ Returns the time that this event is due to be run as a C<DateTime> object
 
 =cut
 
-sub next_run_as_dt {
-    my $self = shift;
-
-    if( $self->set ) {
-        my $dt = DateTime->from_epoch(
-                    epoch     => $self->_last_check_time,
-                    time_zone => $Base->_config('time_zone'),
-                 );
-        return $self->set->next( $dt );                 
-    }        
-    return;
+{   my %cache = ();
+
+    sub next_run_as_dt {
+        my $self = shift;
+
+        ### the time for the next run is EITHER based on the last_run time
+        ### ie, if the last run time is 61 seconds ago, and it's a per minute
+        ### schedule, the 'next run' should return a time of 1 second ago.
+        ### similarly, if the last run time is 2 hours ago, the 'next run' 
+        ### should return a time of 1h59mins ago, which again means it's due.
+        ### The 'last_run' may be 0 (or better yet, undef), in that case, 
+        ### we assume the last run time was NOW. The problem is that if we
+        ### keep asking the 'next_run' time on subsequent requests, it will
+        ### always be based on 'NOW' + 1 minute (for events running every 
+        ### minute), which will always be in the future. Hence we cache
+        ### the answer the first time 'last_run' returns false (ie, never
+        ### run) and use that answer as a fallback, meaning that if we come
+        ### back later (say, 65 seconds later), the 'next run' will be based
+        ### on NOW - 65 + 1 minute, which is 5 seconds ago, and hence the
+        ### event will trigger...
+        my $epoch = $self->last_run || 
+                    $cache{$self}   || 
+                    do { $cache{$self} = time };
+    
+        if( $self->set ) {
+            my $dt = DateTime->from_epoch(
+                        epoch     => $epoch,
+                        time_zone => $Base->_config('time_zone'),
+                     );
+            return $self->set->next( $dt );                 
+        }        
+        return;
+    }
 }
 
 =head2 $bool = $event->run( ... )