compare timestamps rathr than DateTime objects, it's easier to debug that way
[catagits/Catalyst-Plugin-Scheduler.git] / lib / Catalyst / Plugin / Scheduler / Event.pm
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( ... )