Reading the documentation for Topshelf integrations here: https://github.com/dtinteractive/Topshelf.Integrations
And it seems like it should be as simple as scheduling multiple quartz jobs within the HostFactory but it looks like the second scheduled job is the only one that's running.
I'm not really sure how to proceed from here. But I need to schedule two jobs that run on different schedules. The first is supposed to be run daily while the second gets run hourly.
static void Main(string[] args)
{
HostFactory.Run(x =>
{
x.ScheduleQuartzJobAsService(q =>
q.WithJob(() => JobBuilder.Create<TmsIdImportTask>().Build())
.AddTrigger(() =>
TriggerBuilder.Create()
.WithSimpleSchedule(builder => builder
.WithIntervalInMinutes(Int32.Parse(ConfigurationManager.AppSettings["ScheduleImportFrequencyInMinutes"]))
.RepeatForever()).Build())
);
x.ScheduleQuartzJobAsService(q =>
q.WithJob(() => JobBuilder.Create<ImportTmsXMLTask>().Build())
.AddTrigger(() => TriggerBuilder.Create().WithSimpleSchedule(builder =>
builder.WithIntervalInMinutes(Int32.Parse(ConfigurationManager.AppSettings["TMSImportFrequencyInMinutes"]))
.RepeatForever()).Build())
);
x.RunAsLocalSystem();
var description = ConfigurationManager.AppSettings["ServiceDescription"];
x.SetDescription(description);
var displayName = ConfigurationManager.AppSettings["ServiceDisplayName"];
x.SetDisplayName(displayName);
var serviceName = ConfigurationManager.AppSettings["ServiceName"];
x.SetServiceName(serviceName);
});
}
I believe the reason you are having an issue is because you're using
x.ScheduleQuartzJobAsService
instead of
x.ScheduleQuartzJob
I'm just using Quartz for the first time, but I have like 20 different schedules running all within the same host
Create a second service or punt on the Topshelf-Quartz integration and have a service that initializes both Quartz instances and will shut them down.
Topshelf will only host a single [service] process, by design. You can't manage or monitor stuff to any useful degree if Topshelf is hosting multiple processes. It just ends up being an unsustainable pattern.
Related
I am using dask_jobqueue.SGECluster() and when I submit jobs to the grid they are all listed as dask-worker. I want to have different names for each submitted job.
Here is one example:
futures = []
for i in range(1,10):
res = client.submit(slow_pow, i,2)
futures.append(res)
[future.result() for future in as_completed(futures)]
All 10 jobs appear with name dask-worker when checking their status with qsub.
I have tried adding client.adapt(job_name=f'job{i}') within the loop, but no success, name still dask-worker.
Any hints?
The dask-worker is a generic name for the compute allocation from the cluster, it can be changed by providing cluster-specific arguments at the time the cluster is created. For example, for SLURMCluster this would be:
cluster = SLURMCluster('job_extra': ['--job-name="func"'])
SGECluster might have a different syntax.
The actual tasks submitted to dask scheduler will have their names generated automatically by dask and can be viewed through the dashboard, by default on (http://localhost:8787/status).
It's possible to specify a custom name for each task submitted to scheduler by using key kwarg:
fut = client.submit(myfunc, my_arg, key='custom_key')
Note that if you are submitting multiple futures, you will want them to have unique keys:
futs = [client.submit(myfunc, i, key=f'custom_key_{i}') for i in range(3)]
I know I can specify .WithMisfireHandlingInstructionDoNothing() when building the trigger but some of my jobs are triggered via the IScheduler.TriggerJob() method, so without any triggers.
I can detect and log misfires in the ITriggerListener listener but how can I stop Quartz from trying to fire the job again? If I understand correctly .VetoJobExecution is not usable since the job has to be triggered successfully anyway.
Any other ideas?
Edit: my implementation
JobDataMap jobData = new JobDataMap(data);
IJobDetail jobTemplate = await jobScheduler.GetJobDetail(jobKey);
var jobTrigger = TriggerBuilder.Create()
.ForJob(jobTemplate)
.UsingJobData(jobData)
.WithSimpleSchedule(s => s.WithRepeatCount(0).WithMisfireHandlingInstructionNextWithRemainingCount())
.StartNow()
.Build();
await jobScheduler.ScheduleJob(jobTrigger);
Well if you just want the TriggerJob behavior you can achieve that just by adding one simple trigger to scheduler that is going to trigger immediately and configure retry policy for that. So if you can change the call sites of TriggerJob to create a simple trigger instead (maybe an extension method that allows to define the policy), the Quartz source for TriggerJob is here.
I think I've got it.
You have to use the WithMisfireHandlingInstructionNextWithRemainingCount policy, and WithRepeatCount(0).
But the trick here is to set the right value in the IScheduler MisfireThreshold to the misfire to be considered as a real misfire. I mean, if your misfire threshold is set to 60 seconds (default) then any job not executed in less than 60 seconds from schedule, will NOT be considered as a misfire. And so, the misfire policy will not be used.
In my case, with 3 second duration jobs, I had to set the WithMisfireThreshold to 1 second or less.
This way, the job is not retried if "really misfired".
We have installed quartz.net scheduler service and configured a (memory)job to run daily # 10 pm. In case the server hosting this service is restarted, is there a way to force the job to run as soon as the service comes up? In normal scenario job should fire at 10pm as scheduled, but whenever the server/service is restarted, we want the job to run immediately even if it is not scheduled to run at that time. If there's some configuration value to achieve this, that would be the best option.
Write a little code that reads a small xml file (custom one of your own doing)....
and put it in your startup code.
foreach( xmlElement in yourXmlFile)
{
string someJobName= ""; /* read xml for jobName */
String someJobGroup= ""; /* read xml for job group name */
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity(someJobName, someJobGroup)
.startNow()
.build();
}
You can perform this with the help of WithMisfireHandlingInstructionFireAndProceed method of CronScheduleBuilder as shown below:
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSchedule(CronScheduleBuilder
.WeeklyOnDayAndHourAndMinute(DayOfWeek.Monday, 09, 00)
.WithMisfireHandlingInstructionFireAndProceed()
//MISFIRE_INSTRUCTION_FIRE_NOW
.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById("GTB Standard Time"))
)
//.ForJob(myJobKey)
.Build();
scheduler.ScheduleJob(job, trigger);
I have some Quartz.Net jobs which are running on a Schedule
scheduler.ScheduleJob(
new JobDetailImpl("MarkAsSolutionReminderJob", typeof(MarkAsSolutionReminderJob)),
new CalendarIntervalTriggerImpl("MarkAsSolutionReminderJobTrigger", IntervalUnit.Hour, 6));
Is it possible for me to manually trigger this Job to run when I want it to?
So it continues to run as normal, but in a specific piece of code I might want to just run it out of schedule once or twice. But it doesn't affect the scheduled job?
Is it possible for me to manually trigger this Job to run when I want it to?
Yes, you can trigger this job as and when you need.
Use void TriggerJob(JobKey jobKey) method for this as below:
scheduler.TriggerJob(new Jobkey("MarkAsSolutionReminderJob"));
If you want to pass some data to the job while executing it on demand, you can also do that by just using another overload void TriggerJob(JobKey jobKey, JobDataMap data); of the same method as below:
Dictionary<string, string> data = new Dictionary<string, string>();
//populate dictionary as per your needs
JobDataMap jobData = new JobDataMap(data);
scheduler.TriggerJob(new Jobkey("MarkAsSolutionReminderJob"),jobData);
I have the web application in visual studio web express and having db in sql server express.
I want to perform insert 100 records on 5:00 PM daily.web application is developed in asp.net MVC and vb.net. and deployed on server machine with IIS 7.5. what logic i should follow?
For me i'm using this approach and it's good till now :)
I've enum with Tasks to do and the time for the task to restart and this time in seconds like this:
public enum ScheduledTasks
{
CleanGameRequests = 120,
AnotherTask = 30,
}
Then i start all my tasks in the Application_Start to ensure that the task will execute while my application is run
protected void Application_Start()
{
...............
// Add the tasks on Application starts
AddTask(ScheduledTasks.CleanGameRequests);
AddTask(ScheduledTasks.AnotherTask);
}
OK now here is the trick :)
in the AddTask method i just add new empty item to cache and set the AbsoluteExpiration for it according to the task time and the call the suitable method for this task.
Actually my i couldn't explain the idea very clear but here is the code:
private static CacheItemRemovedCallback _onCacheRemove;
private void AddTask(ScheduledTasks task)
{
// Add my `CacheItemRemoved` method to be called on cache removed
_onCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
// Add new key to the cache with the name of this task
// and Expiration time acccordin to the task
HttpRuntime.Cache.Insert(task.ToString(), (int)task, null,
DateTime.Now.AddSeconds((int)task), Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, _onCacheRemove);
}
Then all I've to do is to select suitable method for each task in the CacheItemRemoved method :
public void CacheItemRemoved(string key, object time, CacheItemRemovedReason r)
{
//Get Task enum object
var task = (ScheduledTasks)Enum.Parse(typeof(ScheduledTasks), key);
// Select the suitable method to depending on the Task Enum object
switch (task)
{
case ScheduledTasks.CleanGameRequests:
GameRequest.CleanUp();
break;
case ScheduledTasks.AnotherTask:
Service.AnotherTask();
break;
}
// Don't forget to re-add the task to the cache to do it again and again
AddTask(task);
}
Last thing remain for your case is to check the time if it's 5:00 PM and i advice you to put this check in your Service class.
Hope this helped you :)
Since you are using Sql server express edition you can't create scheduled jobs in sql side. But you can try other options like.
Quartz.Net
Service Broker approach
Windows services (If your hosting provider allows)