I'm actually working in Grails 3.x and I need to use Quartz Cron expressions. I've implemented successfully regular cron expression and works correctly, but now what I need to do is User (from a GUI) change that cron expression for any other he/she wants.
This is my Job
class ScheduleJob
{
static triggers =
{
cron name: 'myTrigger', cronExpression: "*/5 * * * * ?"
}
def execute()
{
println "------ Every 5 seconds"
}
}
I would appreciate so much if someone could help me to know how to do that, thanks for your time. :D
You have a number of options. One thing you can do is call ScheduleJob.schedule(' your cron expression goes here ').
You could also go get the job manager bean from the application context and reconfigure job beans there.
Some of the info at http://www.tothenew.com/blog/removing-triggers-and-rescheduling-a-quartz-2-job-programatically/ might be helpful.
Related
I am trying to create a cron job which run some smoke tests every 10 minutes, my seedjob looks like this :
multiBranchJobs.each { currentJob ->
multibranchPipelineJob(currentJob.name) {
branchSources {
git {
remote(currentJob.projectGitUrl)
credentialsId(currentJob.credentials)
includes(currentJob.includes)
}
}
orphanedItemStrategy {
discardOldItems {
numToKeep(20)
}
}
triggers {
cron "H/5 * * * *"
periodic 60
}
}
}
the problem with the current approach is that it will get executes only if it detects changes in the SCM, which is not the case for the smoke tests. I need to run it every 5 minutes regardless of commits in source control. Any clue ?
I'm not entirely sure how to solve your problem, but I think the cron trigger you have is not doing what you think it is. I THINK this will set this trigger on the multibranch indexing job itself. In the UI that is not even an option. Apparently it isn't throwing an error, but I have to wonder if it is actually setting the trigger.
The jobs that get created from the multibranch job must have a Jenkinsfile, right? You can set the triggers in those Jenkinsfiles.
I haven't built jobs using code, so take that into consideration when you review my answer. But it SEEMS to me that you are setting the trigger in the wrong place.
I know how to get the Execution Id and Instance Id of a job using the Job Context. But if i restart a job, is there way to know if the job execution is the first execution or a restart within the job, for instance inside the reader?
No, but there is an open issue asking for that:
https://java.net/bugzilla/show_bug.cgi?id=7473
This is a bit overly complicated (as the other answer noted, there's an issue opened to consider enhancement for the future Batch 1.1).
You could do this:
//
// Assumes JobContext injected into 'jobCtx' field
//
private boolean isRestart() {
JobOperator jo = BatchRuntime.getJobOperator();
JobInstance jobInstance = jo.getJobInstance(jobCtx.getExecutionId());
int numExecutions = jo.getJobExecutions(jobInstance).size();
return numExecutions > 1;
}
I am using Quartz2 Plugin, and am trying to dynamically trigger a very simple job. When the user performs a certain action, the job should be triggered some certain number of minutes in the future, and only run once.
I have tried using the simple 'schedule' method that takes a date and job data:
def sendTime = new Date()
use(groovy.time.TimeCategory) {
sendTime = sendTime + (connectionInstance.timeout).minutes
println "I will send the job at $sendTime"
}
ReportSmssyncTimeoutJob.schedule(sendTime, [connectionId:params.id])
In this setup, I find that the job actually triggers immediately instead of waiting until 'sendTime'.
My second attempt, after looking at the plugin source, was to use a SimpleTrigger
def sendTime = new Date()
use(groovy.time.TimeCategory) {
sendTime = sendTime + (connectionInstance.timeout).minutes
println "I will send the job at $sendTime"
}
// arguments here are: jobKey='test', startTime=sendTime, repeatCount=0, repeatInterval=1 (zero not allowed), job-arguments)
def trigger = TriggerHelper.simpleTrigger(new JobKey("test"), sendTime, 0, 1, [connectionId:params.id])
ReportSmssyncTimeoutJob.schedule(trigger)
In this setup, the job also triggers immediately. Is there something wrong with the SimpleTrigger implementation which prevents it from waiting until startDate?
Unfortunately, switching to the main 'quartz' plugin (which now has support for Quartz 2) is not an option as I am working on a project that has loads of jobs set up to work with the quartz2 plugin.
I asked this on the Grails mailing list and got the answer: this is a bug in the quartz2 plugin. It should be fixed in the next release (bug was noted in 0.2.3).
Update: tested this in v2.1.6.2 of the quartz2 plugin, and can confirm that both of the approaches in my question now work.
I'm having trouble getting my Quartz Job in Grails to run concurrently as expected. Here is what my job looks like. I've commented out the lines that use the Executor plugin but when I don't comment them out, my code works as expected.
import java.util.concurrent.Callable
import org.codehaus.groovy.grails.commons.ConfigurationHolder
class PollerJob {
def concurrent = true
def myService1
def myService2
//def executorService
static triggers = {
cron name: 'pollerTrigger', startDelay:0, cronExpression: ConfigurationHolder.config.poller.cronExpression
}
def execute() {
def config = ConfigurationHolder.config
//Session session = null;
if (config.runPoller == true) {
//def result = executorService.submit({
myService1.doStuff()
myService2.doOtherStuff()
//} as Callable)
}
}
}
In my case, the myService2.doOtherStuff() is taking a very long time to complete which overlaps the next time this job should trigger. I don't mind if they overlap which is why I explicitly added def concurrent = true but it isn't working.
I have version 0.4.2 of the Quartz plugin and Grails 1.3.7. Am I doing something wrong here? Seems like a pretty straightforward feature to use. I'm not opposed to using the Executor plugin but it seems like I shouldn't have to.
I'm not sure it matters but the cronExpression I'm loading from config in this case is meant to execute this job every minute: "0 * * * * ?"
Apparently, there was a hidden config that I was not aware of that was keeping this from working. In my conf folder there was a file called quartz.properties which contained the following property:
org.quartz.threadPool.threadCount = 1
After increasing this number, my job was triggering even when it had not finished the previous execution.
I have an application using Grails Quartz plugin. I need to have two jobs to have multiple instances running, but have separate limitation on number of threads to be used for each job. As far as I understand, I need separate Thread Pools, which is possible by having separate schedulers. However, I cannot figure out how to create multiple schedulers with Quartz plugin.
Assuming you want to use different triggers to start the job multiple times. this works for me.
class MyJob {
static triggers = {
cron name: 'trigger1', cronExpression: "0 30 12 ? * WED"
cron name: 'trigger2', cronExpression: "0 30 12 ? * SAT"
}
def execute() {
// execute task, do your thing here
println "Job executed"
}
}
Finally, about concurrent tasks.
This is from the plug-in page:
By default Jobs are executed in concurrent fashion, so new Job
execution can start even if previous execution of the same Job is
still running.
Quartz plugin 2.0.13
According to the official documentation :
Multiple triggers per job are allowed.
For instance,
class MyJob {
static triggers = {
simple name:'simpleTrigger', startDelay:10000, repeatInterval: 30000, repeatCount: 10
cron name:'cronTrigger', startDelay:10000, cronExpression: '0/6 * 15 * * ?'
custom name:'customTrigger', triggerClass:MyTriggerClass, myParam:myValue, myAnotherParam:myAnotherValue
}