Repository: tapestry-5
Updated Branches:
  refs/heads/master 143e81039 -> 847403b0e


TAP5-2455: if a job doesn't have a valid next execution time, un-schedule it


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/847403b0
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/847403b0
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/847403b0

Branch: refs/heads/master
Commit: 847403b0ea0f508ba90604dea13720942416bc32
Parents: 143e810
Author: Jochen Kemnade <[email protected]>
Authored: Fri Feb 20 10:58:17 2015 +0100
Committer: Jochen Kemnade <[email protected]>
Committed: Fri Feb 20 11:23:36 2015 +0100

----------------------------------------------------------------------
 .../services/cron/PeriodicExecutorImpl.java     | 21 +++++++++++++-
 .../tapestry5/ioc/services/cron/Schedule.java   |  2 +-
 .../ioc/specs/PeriodicExecutorSpec.groovy       | 30 ++++++++++++++++++++
 3 files changed, 51 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/847403b0/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
----------------------------------------------------------------------
diff --git 
a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
 
b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
index cf3c717..f50a077 100644
--- 
a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
+++ 
b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/cron/PeriodicExecutorImpl.java
@@ -22,7 +22,10 @@ import org.apache.tapestry5.ioc.services.cron.PeriodicJob;
 import org.apache.tapestry5.ioc.services.cron.Schedule;
 import org.slf4j.Logger;
 
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
@@ -358,6 +361,8 @@ public class PeriodicExecutorImpl implements 
PeriodicExecutor, Runnable
         try
         {
             jobLock.lock();
+            // TAP5-2455
+            Set<Job> jobsToCancel = null;
 
             for (Job job : jobs)
             {
@@ -368,7 +373,14 @@ public class PeriodicExecutorImpl implements 
PeriodicExecutor, Runnable
 
                 long jobNextExecution = job.getNextExecution();
 
-                if (jobNextExecution <= now)
+                if (jobNextExecution <= 0)
+                {
+                    if (jobsToCancel == null)
+                    {
+                        jobsToCancel = new HashSet<PeriodicExecutorImpl.Job>();
+                    }
+                    jobsToCancel.add(job);
+                } else if (jobNextExecution <= now)
                 {
                     job.start();
                 } else
@@ -376,6 +388,13 @@ public class PeriodicExecutorImpl implements 
PeriodicExecutor, Runnable
                     nextExecution = Math.min(nextExecution, jobNextExecution);
                 }
             }
+            if (jobsToCancel != null)
+            {
+                for (Job job : jobsToCancel)
+                {
+                    job.cancel();
+                }
+            }
         } finally
         {
             jobLock.unlock();

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/847403b0/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/cron/Schedule.java
----------------------------------------------------------------------
diff --git 
a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/cron/Schedule.java
 
b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/cron/Schedule.java
index 3203f8b..f22319e 100644
--- 
a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/cron/Schedule.java
+++ 
b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/cron/Schedule.java
@@ -31,7 +31,7 @@ public interface Schedule
      * Computes the next execution time for a job.
      *
      * @param previousExecution time of previous execution (in system clock 
millis)
-     * @return time of next execution (in system clock millis)
+     * @return time of next execution (in system clock millis) or a value <=0 
to cancel the job's execution
      */
     long nextExecution(long previousExecution);
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/847403b0/tapestry-ioc/src/test/groovy/ioc/specs/PeriodicExecutorSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/PeriodicExecutorSpec.groovy 
b/tapestry-ioc/src/test/groovy/ioc/specs/PeriodicExecutorSpec.groovy
index f84521d..8ef5d13 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/PeriodicExecutorSpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/PeriodicExecutorSpec.groovy
@@ -1,10 +1,14 @@
 package ioc.specs
 
+import org.apache.tapestry5.ioc.services.cron.CronSchedule;
 import org.apache.tapestry5.ioc.services.cron.IntervalSchedule
 import org.apache.tapestry5.ioc.services.cron.PeriodicExecutor
 
+import spock.lang.Issue;
+
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
+import java.util.concurrent.locks.ReentrantLock;
 
 class PeriodicExecutorSpec extends AbstractRegistrySpecification {
 
@@ -24,6 +28,32 @@ class PeriodicExecutorSpec extends 
AbstractRegistrySpecification {
 
     job && job.cancel()
 
+  }
+
+  @Issue('https://issues.apache.org/jira/browse/TAP5-2455')
+  def "One-shot job in the past is not executed"() {
+
+    setup:
+    buildRegistry()
+
+    def schedule = new CronSchedule('0 0 0 1 1 ? 2014')
+
+    def jobExecuted = Boolean.FALSE
+    when:
+
+    def job = getService(PeriodicExecutor).addJob(schedule, "Job in the past", 
{ jobExecuted = Boolean.TRUE; lock.notifyAll() })
+
+    synchronized (jobExecuted) {
+      jobExecuted.wait(2000l)
+    }
+
+    then:
+    !jobExecuted
+    cleanup:
+
+    if (job && !job.isCanceled()){
+      job.cancel()
+    }
 
   }
 }

Reply via email to