hi there I'm using quartz plugin for grails.
when i have just 1 job (i used "create-job" command) everything works as expected!
this is how the job looks like and it will print every 1 second:
class MyFirstJob{
def concurrent = false
static triggers = {
simple name: 'myFirstJobTrigger', startDelay: 1000, repeatInterval: 1000 }
def group = "MyGroup"
def execute(){
println "MyFirstJob run!"
}
}
now if i add another job that should print every 5 sec that look like this:
class MySecondJob{
def concurrent = false
static triggers = {
simple name: 'mySecondJobTrigger', startDelay: 1000, repeatInterval: 5000 }
def group = "MyGroup"
def execute(){
println "MySecondJob run!"
}
}
what will happen now is that job1 will start working only every 5 seconds
it seems that quartz pluging can only have 1 job schedule
i was wondering what am i missing or doing wrong
i even tried the next 2 lines in a file called quartz.properties under conf directory:
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
thanks for your help
The plugin requires the job class filename to end in 'Job'. Therefore, make sure that MyJob2 is in a file named 'My2Job.groovy' in the job folder
Related
I have been trying to find a lightweight method in a Groovy scriptler script to list all currently running jobs of any type. The only method I have found to be reliable is this:
start = System.currentTimeMillis()
def jobsFound = []
def buildingJobs = Jenkins.instance.getAllItems(Job.class).findAll {
it.isBuilding()
}
buildingJobs.each { job->
allRuns = job._getRuns()
allRuns.each { item->
if (!item.isBuilding()) { return } // This job is not building
jobsFound.push(item.getUrl())
}
}
timespent = (System.currentTimeMillis() - start ) / 1000
println "Time: ${timespent} seconds"
println "{jobsFound.size} jobs"
// RESULTS:
// Time: 2.015 seconds. 15 jobs
The problem is that the above enumerates ALL currently running jobs - we have thousands! - then enumerate all builds of each of those running jobs (some jobs have as many as 300 builds). The above can take as long as FIVE minutes to complete depending on how many jobs are currently building.
A much more efficient method is to enumerate the active executors
but this method MISSES the pipeline (aka Workflow) jobs running on the master:
start = System.currentTimeMillis()
def busyExecutors = Jenkins.instance.computers.collect {
c -> c.executors.findAll { it.isBusy() }
}.flatten()
def jobsFound = []
busyExecutors.each { e ->
job = e.getCurrentExecutable()
jobsFound.push(job.getUrl())
}
timespent = (System.currentTimeMillis() - start ) / 1000
println "Time: ${timespent} seconds. ${jobsFound.size} jobs"
// RESULTS:
// Time: 0.005 seconds. 12 jobs
Sure enough the discrepancy between the two counts are pipeline jobs running on the master.
I guess my question boils down to:
Is there a way to efficiently enumerate all jobs running on the master?
Clearly Jenkins does not include the master in computers, and although there is a MasterComputer class, its not clear how to get it or the OffByOneExecutors on which flyweight (pipeline) jobs run.
Not directly with Jenkins types/objects but via Jenkins' Remote access API derived from From Jenkins, how do I get a list of the currently running jobs in JSON?:
http://localhost:8080/api/xml?&tree=jobs[builds[*]]&xpath=/hudson/job/build[building="true"]&wrapper=builds
results in:
<builds>
<build _class="hudson.model.FreeStyleBuild">
<action _class="hudson.model.CauseAction"/>
<action/>
<action/>
<building>true</building>
<displayName>#10</displayName>
<duration>0</duration>
<estimatedDuration>3617</estimatedDuration>
<executor/>
<fullDisplayName>Freestyle-Project #10</fullDisplayName>
<id>10</id>
<keepLog>false</keepLog>
<number>10</number>
<queueId>2</queueId>
<timestamp>1499611190781</timestamp>
<url>http://localhost:8080/job/Freestyle-Project/10/</url>
<builtOn/>
<changeSet _class="hudson.scm.EmptyChangeLogSet"/>
</build>
</builds>
Unfortunately <builtOn/>, which, I guess, is supposed to refer to the node, isn't supplied in my Jenkins v2.60.1 (yet?).
With:
http://localhost:8080/api/json?pretty=true
you get:
...
"nodeDescription" : "the master Jenkins node",
...
"jobs" : [
{
"_class" : "hudson.model.FreeStyleProject",
"name" : "Freestyle-Project",
"url" : "http://xmg:8080/job/Freestyle-Project/",
"color" : "aborted_anime"
}
]
...
which you can filter then with:
nodeDescription.equals('the master Jenkins node') && color.endsWith('_anime').
I have grails 1.3.7 and quartz plugin 0.4.2 for cron jobs.
class MyJob {
static triggers = {}
void execute() {
//some doings.
}
}
Somewhere in my code I have dynamic scheduling of my job like that:
MyJob.schedule(cronExpression)
Every time I schedule new cron job it creates new one and it works together with previously created jobs. But I want to replace old cron jobs of MyJob with new one each time.
Maybe I was wrong in my understanding but I tried to add
def concurrent = false
It didn't help.
Is there any way to stop all jobs of some job class?
Thank you!
UPD: As I understand there is no such thing as InterruptableJob in this version of quartz plugin. Am I right?
Finally I've found way how to unschedule job and schedule another one.
First I've added a group for job:
class MyJob {
def group = 'jobGroupName'
static triggers = {}
void execute() {
// some stuff
}
}
Also I've found JobManagerService inside plugin with very useful methods. But I was looking into source codes to get how it works correctly. After some time my solutions become in next code (maybe it's raw yet, but it works):
class MyService {
def jobManagerService
def rescheduleJob() {
def job = jobManagerService.getJob('jobGroupName').first()
Scheduler scheduler = jobManagerService.quartzScheduler
Trigger trigger = scheduler.getTriggersOfJob(job, 'jobGroupName').first()
if (!jobManagerService.unscheduleJob(trigger.group, trigger.name)) {
log.warn('Failed during unscheduling job')
} else {
MyJob.schedule(newCronExpression)
}
}
}
It's not clear sometimes which name and group required in service methods. So debug and sources helped me with this.
I want to execute a cron job at a certain time (10pm) every day. Currently I am using following code but it is not working:
class ReviewBatchJob {
private static final logger = LogFactory.getLog(this)
def batchReviewScheduler
static triggers = {
cron cronExpression: "0 0 22 1/1 * ? *"
}
def execute() {
batchReviewScheduler.reviewBatch()
}
}
You should just be able to use an expression of 0 0 22 * * ?.
I'm assuming you're using the quartz plugin; if you don't have it installed, you'll need to. Here's a good reference with quartz cron expression examples.
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
}