提交 1269cca9 编写于 作者: V Vojtech Juranek 提交者: Kohsuke Kawaguchi

Added possibility to run tasks with variable delay intervals - analogs to...

Added possibility to run tasks with variable delay intervals - analogs to PeriodicWork and AsyncPeriodicWork classes, but with variable delay interval.
上级 2c7961e7
package hudson.model;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.triggers.SafeTimerTask;
import hudson.triggers.Trigger;
import java.util.Random;
import java.util.logging.Logger;
/**
* Extension point which allows scheduling a task with variable interval. Interval in evaluated every time before next
* task is scheduled by calling {@link #getRecurrencePeriod()}. Task to be scheduled is obtain by calling {@link #getNewInstance()}.
*
* <p>
* This class is similar to {@link PeriodicWork}. The main difference is in re-evaluating delay interval every time.
* See {@link PeriodicWork} for details. Analog of {@link AsyncPeriodicWork} is {@link AsyncAperiodicWork}.
*
* @author vjuranek
*
*/
public abstract class AperiodicWork extends SafeTimerTask implements ExtensionPoint{
protected final Logger logger = Logger.getLogger(getClass().getName());
/**
* Gets the number of milliseconds between successive executions.
*
* <p>
* Jenkins calls this method every time the timer task is scheduled.
*
*/
public abstract long getRecurrencePeriod();
/**
* Gets new instance of task to be executed. Method should return new instance each time, as there no check, if previously
* scheduled task already finished. Returning same instance could lead to throwing {@link IllegalStateException} (especially
* in case of {@link AsyncAperiodicWork}) and therefore scheduling of next tasks will be broken.
*
* @return AperiodicWork - timer task instance to be executed
*/
public abstract AperiodicWork getNewInstance();
/**
* Gets the number of milliseconds till the first execution.
*
* <p>
* By default it chooses the value randomly between 0 and {@link #getRecurrencePeriod()}
*/
public long getInitialDelay() {
return Math.abs(new Random().nextLong())%getRecurrencePeriod();
}
@Override
public final void doRun() throws Exception{
doAperiodicRun();
Trigger.timer.schedule(getNewInstance(), getRecurrencePeriod());
}
protected abstract void doAperiodicRun();
/**
* Returns all the registered {@link AperiodicWork}s.
*/
public static ExtensionList<AperiodicWork> all() {
return Hudson.getInstance().getExtensionList(AperiodicWork.class);
}
}
package hudson.model;
import hudson.security.ACL;
import hudson.util.StreamTaskListener;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import org.acegisecurity.context.SecurityContextHolder;
/**
* {@link AperiodicWork} that takes a long time to run. Similar to {@link AsyncPeriodicWork}, see {@link AsyncPeriodicWork} for
* details and {@link AperiodicWork} for differences between {@link AperiodicWork} and {@link PeriodicWork}.
*
* @author vjuranek
*
*/
public abstract class AsyncAperiodicWork extends AperiodicWork {
/**
* Name of the work.
*/
public final String name;
private Thread thread;
protected AsyncAperiodicWork(String name) {
this.name = name;
}
/**
* Schedules this periodic work now in a new thread, if one isn't already running.
*/
@Override
public final void doAperiodicRun() {
try {
if(thread!=null && thread.isAlive()) {
logger.log(Level.INFO, name+" thread is still running. Execution aborted.");
return;
}
thread = new Thread(new Runnable() {
public void run() {
logger.log(Level.INFO, "Started "+name);
long startTime = System.currentTimeMillis();
StreamTaskListener l = createListener();
try {
SecurityContextHolder.getContext().setAuthentication(ACL.SYSTEM);
execute(l);
} catch (IOException e) {
e.printStackTrace(l.fatalError(e.getMessage()));
} catch (InterruptedException e) {
e.printStackTrace(l.fatalError("aborted"));
} finally {
l.closeQuietly();
}
logger.log(Level.INFO, "Finished "+name+". "+
(System.currentTimeMillis()-startTime)+" ms");
}
},name+" thread");
thread.start();
} catch (Throwable t) {
logger.log(Level.SEVERE, name+" thread failed with error", t);
}
}
protected StreamTaskListener createListener() {
try {
return new StreamTaskListener(getLogFile());
} catch (IOException e) {
throw new Error(e);
}
}
/**
* Determines the log file that records the result of this task.
*/
protected File getLogFile() {
return new File(Hudson.getInstance().getRootDir(),name+".log");
}
/**
* Executes the task.
*
* @param listener
* Output sent will be reported to the users. (this work is TBD.)
* @throws InterruptedException
* The caller will record the exception and moves on.
* @throws IOException
* The caller will record the exception and moves on.
*/
protected abstract void execute(TaskListener listener) throws IOException, InterruptedException;
}
......@@ -23,23 +23,23 @@
*/
package hudson.triggers;
import antlr.ANTLRException;
import static hudson.init.InitMilestone.JOB_LOADED;
import hudson.DependencyRunner;
import hudson.DependencyRunner.ProjectRunnable;
import hudson.ExtensionPoint;
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.init.Initializer;
import static hudson.init.InitMilestone.JOB_LOADED;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.AperiodicWork;
import hudson.model.Build;
import hudson.model.ComputerSet;
import hudson.model.Describable;
import hudson.model.Hudson;
import hudson.model.Item;
import hudson.model.Project;
import hudson.model.PeriodicWork;
import hudson.model.Project;
import hudson.model.TopLevelItem;
import hudson.model.TopLevelItemDescriptor;
import hudson.scheduler.CronTab;
......@@ -48,18 +48,20 @@ import hudson.util.DoubleLaunchChecker;
import java.io.InvalidObjectException;
import java.io.ObjectStreamException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.ArrayList;
import java.util.Timer;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import antlr.ANTLRException;
/**
* Triggers a {@link Build}.
*
......@@ -276,6 +278,10 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
// start all PeridocWorks
for(PeriodicWork p : PeriodicWork.all())
timer.scheduleAtFixedRate(p,p.getInitialDelay(),p.getRecurrencePeriod());
// start all AperidocWorks
for(AperiodicWork p : AperiodicWork.all())
timer.schedule(p,p.getInitialDelay());
// start monitoring nodes, although there's no hurry.
timer.schedule(new SafeTimerTask() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册