Quartz Scheduler Job Auto Termination - quartz-scheduler

How do I create a Quartz Scheduler job that terminates automatically after given amount of time (if running job takes too much time)?

A Quartz scheduler has no built-in functionality to interrupt a job by itself after a given amount of time.
If you dont want to interrupt Jobs (see the interface InterruptableJob) manually (for example with rmi), you could easily establish such a automatically termination.
Either:
When starting a scheduler, fork a deamon-thread that runs periodically and checks whether some of the currently running jobs must be interrupted. For Example you could use a JobDataMap to store the maximum execution time on a per job instance basis.
Each Job could control its maximum execution time in a similar way.

To stop a job from the inside of the job itself the easiest way is to throw an exception after a specific amount of time. For example:
public class MyJob : IJob
{
Timer _t;
public MyJob()
{
TimeSpan maxRunningTime = TimeSpan.FromMinutes(1);
_t = new Timer(delegate { throw new JobExecutionException("took to long"); }, null, (int) maxRunningTime.TotalMilliseconds,
-1);
}
public void Execute(IJobExecutionContext context)
{
// do your word
// destroy T before leaving
_t = null;
}
}
Hope it helps :)

Related

Disabling busy cursor for eclipse Job

This code does what I need, with the exception that there is a quick switch between the normal cursor, and the busy cursor happening extremely fast.
/* this code is run inside the createPartControl(Composite parent) method of a ViewPart */
Job job = new Job("refreshing")
{
#Override
protected IStatus run(IProgressMonitor monitor)
{
while (data.isReading())
{
Display.getDefault().syncExec(new Runnable()
{
#Override
public void run()
{
treeViewer.setInput(DataView.this.dataModel.getArray());
}
});
}
return Status.OK_STATUS;
}
};
job.schedule();
So is there a way of disabling the busy cursor of a Job in eclipse?
Also, could this happen because the Job is called in a GUI class?
Call
job.setSystem(true);
before you schedule the job. From the JavaDoc:
Sets whether or not this job is a system job. System jobs are
typically not revealed to users in any UI presentation of jobs. Other
than their UI presentation, system jobs act exactly like other jobs.
If this value is not explicitly set, jobs are treated as non-system
jobs. This method must be called before the job is scheduled.
However I think the busy cursor is coming from the BusyIndicator.showWhile call in AbstractTreeViewer.createChildren which the tree setInput will call. I don't think you can do anything about.

where should I locatemy Quartz Code in asp.net

I have an asp.net website and want to do a task once a day.
the task is: sending email to users 2 days before expiration of their registration.
I used Quartz.NET version 1.0. I have wrote a sample code that opens a window in each second. Now I don't know where should I locate this code in my asp.net project?! it is now in a simple page. I want it to be independent from pages.
public class DumbJob : IJob
{
public DumbJob()
{
}
public void Execute(JobExecutionContext context)
{
Console.WriteLine("DumbJob is executing.");
System.Windows.Forms.MessageBox.Show("NICE");
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();
// get a scheduler
IScheduler sched = schedFact.GetScheduler();
sched.Start();
// construct job info
JobDetail jobDetail = new JobDetail("myJob", null, typeof(DumbJob));
// fire every hour
Trigger trigger = TriggerUtils.MakeSecondlyTrigger();//.MakeHourlyTrigger();
// start on the next even hour
trigger.StartTimeUtc = TriggerUtils.GetEvenSecondDate(DateTime.UtcNow);
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger);
}
}
There are various ways you can do that...but certainly it's probably better o build some sort of console applications for your case.
Frankly the simplest of which could be a windows schedule task that would trigger every day and launch an exe program (that you'd write using console dotnet) that would check soon-to-expire users and send an email when found...
If you don't want to have user + email code in various places (and centralize all this in your dotnet web app), then I'd create a SOAP/REST end point in your .NET webapp that would be called by a thin client, which would be scheduled by that "windows schedule task"
Quartz would give you more flexibility when it comes to scheduling and doing more enterprise things like job clustering / job high availability / job monitoring for example...
But that'd still be a .NET console app which would start a quartz scheduler, create a trigger, and run forever...(possibly wrapped into a windows "wrapper" service for more control)

Get executed jobs form the scheduler in Quartz

I want to retrieve scheduled but already executed jobs from the scheduler in Quartz. Is there any way to do so?
Well, first you need to retrieve a list of all currently scheduled jobs:
Scheduler sched = new StdSchedulerFactory().getScheduler();
List jobsList = sched.getCurrentlyExecutingJobs();
Then, it's a matter of iterating the list to retrieve the context for reach job. Each context has a getPreviousFireTime().
Iterator jobsIterator = jobsList.listIterator();
List<JobExecutionContext> executedJobs = new List<JobExecutionContext>();
while(jobsIterator.hasNext())
{
JobExecutionContext context = (JobExecutionContext) jobsIterator.next();
Date previous = context.getPreviousFireTime();
if (previous == null) continue; //your job has not been executed yet
executedJobs.Add(context); //there's your list!
}
The implementation may be slightly different depending on which quartz you use (java or .net) but the principle is the same.
Set the property JobDetail.setDurability(true) - which instructs Quartz not to delete the Job when it becomes an "orphan" (when the Job not longer has a Trigger referencing it).

Eclipse Progress View is not refreshing when running many jobs

I've problem with running big number of concurrent Jobs in my Eclipse RCP application. When I start 100 Jobs (like the one bellow), they execute normally but after they are finished they are still visible in Progress View for about 10 seconds. I would like Progress View to clear Jobs immediately after they are finished. If I start less Jobs (eg. 10) Progress View refreshes it self immediately.
class MyJob extends Job
{
public MyJob(String name) {
super(name);
}
public IStatus run(IProgressMonitor monitor){
//SOME EXPENSIVE COMPUTATIONS
BigInteger bigint = new BigInteger("0");
for ( int i=0 ; i<100 ; i++ ) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
bigint = bigint.add(new BigInteger(Integer.toString(i)));
}
monitor.done();
System.out.println(new Random().nextInt());
return new Status(IStatus.OK, "foo", "OK");
}
}
each job is scheduled as a separate thread and in case there are lots of them locking/synchronization/thread management mechanisms take some overhead. for example some internal Eclipse Jobs code explicitly puts progress-bar-feedback mechanism into sleep for 250ms. such solutions probably pile up into long delays.
anyway having 100 entries in Progress View is not user firendly. I'd suggest grouping those jobs with Job.setProgressGroup(). perhaps having less entries in the view will cover up slow responsiveness.
In a case like this, I'd say it's better to allocate your own Threads than to use Jobs. Your 100 Jobs are going to start using the Job Threads that would be used to do Workbench maintenance. Allocating your own Threads means the Jobs Thread pool doesn't grow to the max value and stay there.
I'd have one Job that starts your Threads and reports progress to the Progress View. You could use SubMonitor to split the main IProgressMonitor into 100 so each of the Thread/Runnable pairs you start can report progress back to the main Job.

Help and advice needed working with Quartz.NET NthIncludedDayTrigger

I've started using Quartz.NET recently, and so far, it's been really
helpful. Now, I'm trying to use it to create a job that runs once a
month using a NthIncludedDayTrigger (I want to use the
NthIncludedDayTrigger as eventually I will be specifying a calendar to
exclude weekends/holidays).
To familiarise myself with the code, I've
set up a simple console application to create an NthIncludedDayTrigger
where the first fire time will be 15 seconds from now:
static void Main(string[] args)
{
IScheduler scheduler = StdSchedulerFactory.DefaultScheduler;
scheduler.Start();
var jobDetail = new JobDetail("Job name", "Group name", typeof(SomeIJobImplementation));
var trigger = new NthIncludedDayTrigger();
trigger.Name = "Trigger name";
trigger.MisfireInstruction = MisfireInstruction.NthIncludedDayTrigger.DoNothing;
trigger.IntervalType = NthIncludedDayTrigger.IntervalTypeMonthly;
//I'm using the following while experimenting with the code (AddHour(1) to account for BST):
trigger.FireAtTime = DateTime.UtcNow.AddHours(1).AddSeconds(15).ToString("HH:mm:ss");
//I'm using the following while experimenting with the code:
trigger.N = DateTime.Today.Day;
Console.WriteLine("Started, press any key to stop ...");
Console.ReadKey();
scheduler.Shutdown(false);
}
...
public class SomeIJobImplementation : IJob
{
public void Execute(JobExecutionContext context)
{
Logger.Write(String.Format(
"Job executed called at {0}",
DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss")), null, 1,
TraceEventType.Information);
}
}
Running this results in the job being executed multiple times
(approximately once per second) for one minute. I'm using an ADO.NET
job store and can see in my database that QRTZ_TRIGGERS.NEXT_FIRE_TIME
is set to the last executed time, i.e. doesn't seem to be scheduled to
run again.
I expected the above code to run the job once (after about 15
seconds), then schedule the job to run again in one months time.
Perphaps the issue is just with the way I'm using Quartz.NET whilst
I've been experimenting or, maybe, my expectations are wrong? Either
way, I would be most grateful for any help/suggestions to explain the
behaviour I've observed, and what I need to change to get the
behaviour I want.
I must be late but I was trying to implement the same solution and ended up here.
I reckon you should star the scheduler after you've defined jobs and triggers.