I'm trying to perform the following code on a console application that uses Quarz.NET, but I got the following exception.
Here's the snippet of code
public Task AddSchedule(FlussoAnagraficaItem item)
{
if(this.scheduler == null) throw new Exception("scheduler is null, has the InitAsync method been invoked?");
var jobItemType = this.jobCreatorFactory.CreateJobFromAnagraficaFlussiItem(item);
// define the job and tie it to our HelloJob class
IJobDetail job = JobBuilder.Create(jobItemType)
.WithIdentity(item.Description, "sender")
.Build();
// Trigger the job to run now, and then repeat every 10 seconds
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity($"trigger_{item.Description}", "sender")
.StartNow().WithCronSchedule(item.Timespan)
.Build();
// Tell quartz to schedule the job using our trigger
return this.scheduler.ScheduleJob(job, trigger);
}
Where item.Timespan is "00 16 * * 5" , what's wrong?
Thanks
Related
I have Jenkins jobs that trigger twice a day and I would like to know if the current build is the first cron trigger of the day or not and do some action.
My cron job is as below
triggers {
// regression --> 3:00GMT, 14:00GMT
cron("00 3 * * 1-5 \n 00 14 * * 1-5")
}
Can I set some boolean param in my Jenkins file to check if it's the first trigger of the day?
The simplest option would be to check the build history. If the previous build was executed on the previous day, then the current build is the first build of the day. The logic must be defined in the executed job configurations.
The currentBuild object is an instance of the org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper class which provides all necessary information.
steps {
echo "The first build of the day started by trigger: ${isFirstBuildOfDayStartedByTrigger(currentBuild)}"
}
// ...
boolean isFirstBuildOfDayStartedByTrigger(currentBuild) {
if (isStartedByTrigger(currentBuild)) {
return false
}
def today = toLocalDate(currentBuild.startTimeInMillis)
def build = currentBuild.previousBuild
while(build != null) {
if (toLocalDate(build.startTimeInMillis).isBefore(today)) {
return true
}
if (isStartedByTrigger(build)) {
return false
}
build = build.previousBuild
}
return true
}
LocalDate toLocalDate(long millis) {
return Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDate()
}
boolean isStartedByTrigger(build) {
// TODO: use build.buildCauses or build.getBuildCauses('cause.class.Name')
// to analyze if the job was started by trigger
return true // or false
}
You have to figure out which build cause is added when the job is started by trigger.
If you just want to find the first build of the day executed by anything or anyone, then the code is much simpler:
steps {
echo "The first build of the day: ${isFirstBuildOfDay(currentBuild)}"
}
boolean isFirstBuildOfDay(currentBuild) {
def today = toLocalDate(currentBuild.startTimeInMillis)
def previousBuild = currentBuild.previousBuild
return previousBuild == null || toLocalDate(previousBuild.startTimeInMillis).isBefore(today)
}
LocalDate toLocalDate(long millis) {
return Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalDate()
}
I used the new date API which I think is not whitelisted, so you have to put that code to the Jenkins library or approve the used method signatures.
Found the answer, it's simple but working fine for me.
First I am checking if this is a scheduled job or not and the current hour is less than 5 (scheduled job runs before 5)
def isItFirstScheduledJob = (params.JOB_IS_SCHEDULED && new Date().getHours() < 5) ? true : false
I have a Jenkins job which is scheduled for a specific time. I want to modify that timing programmatically.
I tried to modify the build by installing Schedule Build plugin and modify it using http://jenkins_url/job/jobname/build?delay=3344sec. But this will put the job in quiet period which holds the java thread. I'm looking to modify the Schedule entry without putting it to quiet period.
You can use the Build Triggers -> Build periodically job configuration option. Use that to specify the exact time for starting a new build.
If you need to change that time, use the Jenkins REST API to...
programmatically retrieve the job configuration in XML format, then
modify the scheduling time in that configuration (see below)
re-post the new job configuration
In bash, this can be done with a one-liner (using curl and sed) to modify the XML section below (the example schedules a run for noon, Feb 29):
[...]
<triggers>
<hudson.triggers.TimerTrigger>
<spec>00 12 29 02 * </spec>
</hudson.triggers.TimerTrigger>
</triggers>
[...]
Note:
as a plus you wouldn't depend on any supplementary plugins
caveat: you cannot specify a year in the schedule -- so if you need to schedule builds more than one year in advance then you need some magic on top.
I can't get it to work, but the source code for the plugin references a "schedule" url action and a "date" param.
I tried something like:
http://localhost:8080/job/jobname/job/develop/schedule?date=2020-02-20
Which it didn't reject but I can't see a build.
below is the source code of the action performed when the button is pressed to schedule:
var newRequest = function() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
var sumbitScheduleRequest = function(absoluteUrl, quietPeriodInSeconds, isJobParameterized){
if(isJobParameterized){
// if job has parameters, redirect to build page, so user can set parameters
window.location = absoluteUrl + "build?delay=" + quietPeriodInSeconds + "sec";
}else{
// if job has NO parameters, submit build directly
var csrfCrumb;
var csrfRequest = newRequest();
csrfRequest.onreadystatechange = function() {
if (csrfRequest.readyState === 4) {
if (csrfRequest.status === 200 || csrfRequest.status === 201) {
csrfCrumb = JSON.parse(csrfRequest.responseText);
} else {
// csrf might be deactivated
}
// do the actual submit
var xmlhttp = newRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4) {
if (xmlhttp.status === 200 || xmlhttp.status === 201) {
window.location = absoluteUrl;
return false;
} else {
window.location = absoluteUrl;
return false;
}
}
};
xmlhttp.open("POST", absoluteUrl + "build?delay=" + quietPeriodInSeconds + "sec", true);
if (csrfCrumb) {
xmlhttp.setRequestHeader(csrfCrumb.crumbRequestField, csrfCrumb.crumb)
}
xmlhttp.send();
}
};
csrfRequest.open('GET', rootURL + '/crumbIssuer/api/json', false);
csrfRequest.send();
}
}
I have a cron job which has multiple triggers all triggers have been scheduled for the interval of lets say 5 min, now I need to update job data map at runtime, for that I need that particular trigger which requires to update but I am failing to get that particular trigger, I am doing something like that
String cronExpression = "0 0/5 * * * ?"
String triggername = "mytrigger" + System.currentTimeMillis()
JobDataMap jobDataMap = new JobDataMap([host: config.host, port: config.port, username: config.username, password: config.password])
CronTrigger trigger = TriggerBuilder.newTrigger()
.withIdentity(triggername)
.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)).usingJobData(jobDataMap)
.build()
MyJob.schedule(trigger)
Any idea how can I get that particular trigger which I have to update?
Try something like that:
List<Trigger> triggers = quartzScheduler.jobGroupNames.collect {
quartzScheduler.getJobKeys(GroupMatcher.groupEquals(it)).collect {
quartzScheduler.getTriggersOfJob(it)
}
}.flatten()
It will return all your scheduled triggers. After get them you can do what you need in JobDataMap.
I suggest use a familiar trigger identity, it make easier to find a specific one at runtime.
I saved the trigger name in database, and when I need to update that trigger I simply fetch that trigger like this:
TriggerKey triggerKey = new TriggerKey(triggerName_from_db);
try {
Trigger trigger = quartzScheduler.getTrigger(triggerKey)
if (trigger?.key?.name) {
trigger.jobDataMap['host'] = config.host
trigger.jobDataMap['port'] = config.port
trigger.jobDataMap['username'] = config.username
trigger.jobDataMap['password'] = config.password
}
quartzScheduler.rescheduleJob(triggerKey, trigger)
}catch (SchedulerException ex) {
log.error ex.toString()
}
i use executor service to launch multiple thread to sent request to api and get data back. sometimes i see some threads haven't finished their job yet, the service kill that thread already, how can i force the service to wait until the thread finish their job?
here is my code:
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<List<Book>>> futures = Lists.newArrayList();
final ObjectMapper mapper1 = new ObjectMapper();
for (final Author a : authors) {
futures.add(pool.submit(new Callable<List<Book>>() {
#Override
public List<Book> call() throws Exception {
String urlStr = "http://localhost/api/book?limit=5000&authorId=" + a.getId();
List<JsonBook> Jsbooks = mapper1.readValue(
new URL(urlStr), BOOK_LIST_TYPE_REFERENCE);
List<Book> books = Lists.newArrayList();
for (JsonBook jsonBook : Jsbooks) {
books.add(jsonBook.toAvro());
}
return books;
}
}));
}
pool.shutdown();
pool.awaitTermination(3, TimeUnit.MINUTES);
List<Book> bookList = Lists.newArrayList();
for (Future<List<Book>> future : futures) {
if (!future.isDone()) {
LogUtil.info("future " + future.toString()); <-- future not finished yet
throw new RuntimeException("Future to retrieve books: " + future + " did not complete");
}
bookList.addAll(future.get());
}
and i saw some excepitons at the (!future.isDone()) block. how can i make sure every future is done when executor service shutdown?
I like to use the countdown latch.
Set the latch to the size that you're iterating and pass that latch into your callables, then in your run / call method have a try/finally block that decrements the countdown latch.
After everything has been enqueued to your executor service, just call your latch's await method, which will block until it's all done. At that time all your callables will be finished, and you can properly shut down your executor service.
This link has an example of how to set it up.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html
I have what should be a simple task. I create a new job, make if durable and add add using the IScheduler.AddJob method. The job is registered but for the life of me I can not figure how to assign triggers to it.
This is from the tutorial:
// 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.MakeHourlyTrigger();
// start on the next even hour
trigger.StartTime = TriggerUtils.GetEvenHourDate(DateTime.UtcNow);
trigger.Name = "myTrigger";
sched.ScheduleJob(jobDetail, trigger);