Tricky Quartz.NET Script

Ok, a bit of background here. I have a large-scale web application (MVC3) that does all kinds of unimportant things. I need this web application to be able to schedule special Quartz.NET jobs in an Oracle database . Then I want the tasks to be performed later through the Windows service. Ideally, I would like to schedule them to run at specific intervals, but with the ability to add tasks through a web application.

Basically, the desired architecture is some variation of this:

Web Application ↔ Quartz.NET ↔ Database ↔ Quartz.NET ↔ Windows Service

What I have encoded so far:

  • A Windows service that (currently) schedules and runs tasks. This obviously will not end up, but I wonder if I can save this and change it so that it basically presents as β€œQuartz.NET” in the diagram above.
  • Web application (details, I think, are not very important here)
  • Jobs (which are actually just another Windows service)

And a few important points:

  • It must be started from a Windows service, and it must be scheduled through a web application (to reduce the load on IIS)
  • The architecture described above may be slightly modified, assuming that the above bullet is still applied.

Now a few questions:

  • Is it possible?
  • Assuming that (1) passes, what do you guys think is the best architecture for this? Look at the first bullet at what I encoded.
  • Can someone please give me some quartz methods that will help me query DB to complete the tasks as soon as they are planned?

There will be generosity in this matter as soon as it is allowed. If the answer is satisfactory before this question, I will still award a reward to the answer poster. So, anyway, if you give a good answer here, you will receive a reward.

+7
source share
1 answer

I will try to answer your questions in the order in which you have them.

  • Yes it is possible. This is actually a general way to work with Quartz.Net. In fact, you can also write an ASP.Net MVC application that manages the Quartz.Net schedulers.

  • Architecture. Ideally and at a high level, your MVC application will use the Quartz.Net API to communicate with the Quartz.Net server, which is installed somewhere as a Windows service. Quartz.Net uses remote access for remote communication, so any restrictions on the use of remote access apply (for example, it is not supported in Silverlight, etc.). Quartz.Net provides the ability to install it as a Windows service out of the box, so there is not much work here, except to configure the service itself to use (in your case) AdoJobStore, as well as enabling Remoting. Care must be taken to properly install the service, so if you have not already done so, look in this message .

Inside your MVC application, you will want to get a link to the scheduler and save it as a singleton. Then, in your code, you will schedule tasks and receive information about the scheduler through this unique instance. You can use something like this:

public class QuartzScheduler { public QuartzScheduler(string server, int port, string scheduler) { Address = string.Format("tcp://{0}:{1}/{2}", server, port, scheduler); _schedulerFactory = new StdSchedulerFactory(getProperties(Address)); try { _scheduler = _schedulerFactory.GetScheduler(); } catch (SchedulerException) { MessageBox.Show("Unable to connect to the specified server", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } public string Address { get; private set; } private NameValueCollection getProperties(string address) { NameValueCollection properties = new NameValueCollection(); properties["quartz.scheduler.instanceName"] = "RemoteClient"; properties["quartz.scheduler.proxy"] = "true"; properties["quartz.threadPool.threadCount"] = "0"; properties["quartz.scheduler.proxy.address"] = address; return properties; } public IScheduler GetScheduler() { return _scheduler; } } 

This code configures the Quart.Net client. Then, to access the remote scheduler, just call

 GetScheduler() 
  • Requests Here is an example code for receiving all tasks from the scheduler:

     public DataTable GetJobs() { DataTable table = new DataTable(); table.Columns.Add("GroupName"); table.Columns.Add("JobName"); table.Columns.Add("JobDescription"); table.Columns.Add("TriggerName"); table.Columns.Add("TriggerGroupName"); table.Columns.Add("TriggerType"); table.Columns.Add("TriggerState"); table.Columns.Add("NextFireTime"); table.Columns.Add("PreviousFireTime"); var jobGroups = GetScheduler().GetJobGroupNames(); foreach (string group in jobGroups) { var groupMatcher = GroupMatcher<JobKey>.GroupContains(group); var jobKeys = GetScheduler().GetJobKeys(groupMatcher); foreach (var jobKey in jobKeys) { var detail = GetScheduler().GetJobDetail(jobKey); var triggers = GetScheduler().GetTriggersOfJob(jobKey); foreach (ITrigger trigger in triggers) { DataRow row = table.NewRow(); row["GroupName"] = group; row["JobName"] = jobKey.Name; row["JobDescription"] = detail.Description; row["TriggerName"] = trigger.Key.Name; row["TriggerGroupName"] = trigger.Key.Group; row["TriggerType"] = trigger.GetType().Name; row["TriggerState"] = GetScheduler().GetTriggerState(trigger.Key); DateTimeOffset? nextFireTime = trigger.GetNextFireTimeUtc(); if (nextFireTime.HasValue) { row["NextFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime(nextFireTime.Value.DateTime); } DateTimeOffset? previousFireTime = trigger.GetPreviousFireTimeUtc(); if (previousFireTime.HasValue) { row["PreviousFireTime"] = TimeZone.CurrentTimeZone.ToLocalTime(previousFireTime.Value.DateTime); } table.Rows.Add(row); } } } return table; } 

You can view this code on Github

+25
source

All Articles