[#QTZ-196] New trigger type `DailyTimeIntervalTrigger`

advertisement
[QTZ-196] New trigger type 'DailyTimeIntervalTrigger' Created: 26/Jul/11
Updated:
27/Jul/12 Resolved: 08/Sep/11
Status:
Project:
Component/s:
Affects
Version/s:
Fix Version/s:
Closed
Quartz Scheduler
Triggers
2.0.1
Type:
Reporter:
Resolution:
Labels:
Remaining
Estimate:
Time Spent:
Original
Estimate:
New Feature
uday ogra
Fixed
None
Not Specified
Attachments:
newTrigger.diff
quartz-2.1.0rc_with_endingDailyAfterCount_2.jar
quartz-2.1.0rc_with_endingDailyAfterCount.jar
quartz-2.1.0SNAPSHOT.tar.gz
quartz-2.1.0SNAPSHOT_with_repeatCount.jar
quartz-2.1.0SNAPSHOT_with_repeatCount_v2.jar
Quartz 2.1.0
Terracotta
Target:
Fixed In
Revision:
2.1
Priority:
Assignee:
Votes:
2 Major
Zemian Deng
0
Not Specified
Not Specified
1605
Description
Presently there is no way to schedule a task like this :
"Create a task which should run daily from 6:15 AM to 9:15 AM at the interval of 70 seconds."
This is a very common scenario
Crontime syntax doe not take intervals like 70 seconds,80 minutes etc etc
Comments
Comment by James House [ 26/Jul/11 ]
This cannot be done as a feature of CronTrigger - it is too different from the way the trigger can
work. Just as unix cron cannot support it.
A new trigger type, and takes a start time of day, end time of day, and interval could support it.
Comment by Marko Lahma [ 02/Aug/11 ]
What about SimpleTrigger with DailyCalendar? Will this new trigger be kind of a short-hand
for this?
Comment by James House [ 02/Aug/11 ]
No, that doesn't quite work, because if the intention is to fire at 6:15 every day, that won't work
out if the interval is a number that does not come back around to 6:15 the next day (it may
instead be 6:17 or such).
Comment by Zemian Deng [ 09/Aug/11 ]
James,
You can assign this to me, and I will try to work on it whenever I can.
Comment by James House [ 09/Aug/11 ]
I had started some rough prototyping for this new trigger, and have attached it.
It has finish work to do, and I'm not fully happy with the design, particularly around the "days
of week" property of the trigger (i.e. using a Set<Integer>).
Also no testing has been done (as the coding wasn't done).
Also note that it will need an extension of SimpleTriggerPersistenceDelegate to be able to be
stored in JDBCJobStore (and code in the jdbcjobstore package will need updated to "know"
about the new persistence delegate - see addDefaultTriggerPersistenceDelegates() on
StdJDBCDelegate).
Comment by James House [ 09/Aug/11 ]
Feel free to propose a new approach - just thought I'd attach my work to date as a way of
sharing some of my initial thinking.
Comment by Zemian Deng [ 14/Aug/11 ]
Ahh, Thanks James. I will start what you have.
As for comment on the "days of week" using a set, so far I don't see a problem with that yet,
other than it would make the user harder to enter them in. We can possibly expose a String
expression that parse the week days like in Cron. This will make input little easier.
I will some time next week, so I will take a closer look then.
PS: Are you sure you want to keep the same class name? I thought the name
'DailyTimeIntervalTrigger' stated in this Jira is more shorter and descriptive enough, compare to
the long 'DailyIntervaledTimeRangeTrigger' name.
Comment by Zemian Deng [ 19/Aug/11 ]
I have chosen to use DailyTimeIntervalTrigger name instead. I have added the logic for this
trigger implementation and have checked in the files.
I have yet to impl the SimpleTriggerPersistenceDelegate yet, will look into that next.
Comment by Zemian Deng [ 20/Aug/11 ]
I have added DailyTimeIntervalTriggerPersistenceDelegate by commit r1601.
This new trigger type is ready for use. If there is any users out there awaiting on this, please try
it out.
I have tested it against MySQL storage, and all unit tests passed.
Comment by Zemian Deng [ 20/Aug/11 ]
New trigger implementation for DailyTimeIntervalTrigger and it's related unit tests has been
added.
Svn commit r1601 for 2.0.x branch, and r1605 for trunk.
Comment by James House [ 22/Aug/11 ]
thanks!
Comment by uday ogra [ 07/Sep/11 ]
Thanks a lot Zemain
We were eagerly waiting for this trigger.
I have one doubt. I used SVN to download latest code, but it does not contain any jar file. Are
we supposed to build it. If yes do you maintain build.xml file also or only through maven we
can build it?
Comment by James House [ 07/Sep/11 ]
SVN only contains the source code, and there's only a build file for maven.
There should be an official release-candidate build available within a couple days, and then full
official release build a week or so later.
Comment by uday ogra [ 07/Sep/11 ]
By any chance can we get the build jar as I am facing few issues while building using maven.
By the time you release it officially we could have tested the new trigger on our side
Comment by James House [ 07/Sep/11 ]
Maven can definitely be a pain. Not too fond of it myself.
Here (attached to this issue) is a snapshot build that I just made.
Comment by James House [ 07/Sep/11 ]
Testing and feedback on the new trigger type will be appreciated!
Comment by uday ogra [ 07/Sep/11 ]
Thanks a lot.
Surely we will be doing extensive testing and giving feedback as well
Comment by uday ogra [ 07/Sep/11 ]
I have one small feedback. Can DailyTimeIntervalTrigger take repeat parameter also so that we
can create a trigger like this : Run everyday at 7 PM for 10 times at an interval of 100 seconds.
In this case user need not to specify endtime of the day.
Comment by James House [ 07/Sep/11 ]
Seems like we could provide the convenience of computing the appropriate end time of day
based on the repeat count and interval. This has the problem of being "racy" with the other
settings (what if someone tries to set the end time of day based on repeat count before the
interval has been set?) - but that could be overcome by not computing the end time of day until
the build() method is called on the builder.
What do you think Zemian?
Comment by Zemian Deng [ 07/Sep/11 ]
A repeatTotalCount as stopper to the trigger sounds like a useful feature. I will try to add that in.
Comment by Zemian Deng [ 07/Sep/11 ]
I have added the repeatCount feature to DailyTimeIntervalTrigger. r1649.
It works just like the SimpleTrigger's repeatCount, except it will default to
REPEAT_INDEFINITELY(-1) instead of 0. So if you set it to 3, it will ends your trigger after
firing 4 times. If you do not set repeatCount value, the trigger will work as originally designed,
else it will ends after that number of times of repeatInterval triggers + 1.
The Builder class has also been updated with withRepeatCount(int) method.
I have not add any MISFIRE_INSTRUCTION for this behavior though.
Comment by Zemian Deng [ 07/Sep/11 ]
I have attached new jar so others may test the new feature without building it from source.
Comment by Zemian Deng [ 08/Sep/11 ]
I missed to update the trigger's DailyTimeIntervalTriggerPersistenceDelegate, for new
repeatCount field. Now it's added. r1650.
I am reattaching another new jar for user testing.
Comment by Zemian Deng [ 08/Sep/11 ]
Please note that you MUST delete all your old, existing DailyTimeIntervalTrigger's in database
in order to properly test the new "repeatCount" feature. This is because the repeatCount default
value should be "-1", but before this impl, the storage of this field column already exists, and it
has default to "0"! This repeatCount value will properly store the correct value after you get the
latest code.
Comment by James House [ 08/Sep/11 ]
thanks!
Comment by uday ogra [ 09/Sep/11 ]
Thanks!!!
If we give repeat count than end time should not be mandatory. Right now if endtime is null and
reeat count has some value , it throws an error :
"Start time of day cannot be null!"
Comment by Zemian Deng [ 09/Sep/11 ]
Hello uday,
Your error is contradicting what you are describing. The startTime must be set on trigger, in
regardless what you set repeatCount and the endTime. So have you set start time? Are you using
the DailyTimeIntervalScheduleBuilder? If you do, all these fields will have proper default
values, and you will not get these error.
Can you show your code on how you create the trigger?
Please take a look at DailyTimeIntervalScheduleBuilderTest for examples on how to build the
trigger.
Comment by Zemian Deng [ 09/Sep/11 ]
BTW, the endTime of the trigger is always optional, and it is default to "null". It is only in use if
you set it to some value.
If you set repeatCount to any value other than REPEAT_INFINITELY (which is the default),
then it will overwrite the usage of endTime (even if you set a value for endTime that is.)
Comment by Zemian Deng [ 09/Sep/11 ]
Sorry, I meant to say this on the last post, but it wont' let me edit it, so I will re-add another
comment.
--------------BTW, the endTime of the trigger is always optional, and it is default to "null". It is only in use if
you set it to some value.
If you set repeatCount to any value other than REPEAT_INFINITELY (which is the default),
then it will first check repeatCount has reached, if not, and if endTime is set, it will also check
and see if endTime has reached.
Comment by uday ogra [ 14/Sep/11 ]
Sorry for the delay.Here is the code snippet I am using :
triggerbuilder.withIdentity(CronUtil.getTriggername(task), fullgrpname.toUpperCase())
.forJob(CronUtil.getJobname(task), fullgrpname.toUpperCase()).withSchedule(
DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule().withIntervalInSeconds(
Integer.valueOf(interval)).withRepeatCount(Integer.valueOf(repeat))
.withMisfireHandlingInstructionDoNothing().endingDailyAt(etime)
.startingDailyAt(stime));
All variables are properly initialized and CronUtil is our helper class
If 'etime' is null and 'repeat' has some value it throws 'start time can not be null' kind of
exception even though 'stime' was not null. I know it is contradictory
If I give some value to 'etime' everything goes fine
Comment by uday ogra [ 14/Sep/11 ]
I have one more feedback regarding repeat count.
The current implementation treats Repeat as the total number of times a task has to be executed.
For example if repeat count is 5 and tasks executed 3 times today, it will execute 2 times more
tomorrow and it will be over.
I feel it should be treated as daily repeat count. i.e repeat the task 5 times everyday rather than
total 5 times in its entire lifecycle.
What do you say?
Comment by Zemian Deng [ 14/Sep/11 ]
I think that would make the "repeatCount" not consistent in using compare to other triggers. I
also think keeping the repeatCount as total number of times is much more useful.
What you requested in your case, uday, can be easily done by setting the endingDayOfTime
closer to when you want to stop, and not use repeatCount at all. The number of times to fire
each days is entirely calculable by setting the correct interval and the start, ending of the
DayOfTime range. I think that's more clear and easier to maintain your trigger.
Comment by James House [ 14/Sep/11 ]
I think repeat count as implemented is of limited value for this type of trigger.
By its nature, this type of trigger is going to be used for forever-repeating schedules (firing
during the time window every day forever). I think by its nature it will be very rare that
someone would want a schedule of "fire every 10 minutes between 9:00 and 11:30 every
weekday until there have been 50 firings" - that seems like a very weird business case that
would come up with the "until there have been 50 firings" clause. The more likely limitation
would be "until midnight on July 31, 2012" - and endTime takes care of that nicely.
I think what Uday was looking for was just some syntactic sugar to help calculate the ending
time of day for a schedule such as "fire 5 times with an interval of 10 minutes starting at 9:00
every weekday".
Comment by Zemian Deng [ 14/Sep/11 ]
@James,
I can't comment on how rare the use case of the repeatCount at the moment. But changing it's
meaning will certainly confuse a typical quartz user. If requested is a helping method to
calculate the endingDaily time, then perhaps we can have a DateBuilder help method, or one in
the trigger build. Creating another dailyRepeatCount to limit that is too excessive.
@Uday,
As to answer your problem on eTime example above (posted on 14/Sep/11 05:03 AM)
The exception you're getting is expected because both endingDailyAt() and startingDailyAt()
method will not accept null value. If you want default value for these, simply do not call them!
But calling them with "null" will fail since the trigger builder is validating your input.
Comment by uday ogra [ 14/Sep/11 ]
@James
Yes exactly I was looking for that use case only. Running some task 10 times a day,everyday,
starting at some time, with some interval.So endtime of the day would not be required in this
case. But I think depending on the RepeatCount's value I can calculate the endtime of the day by
myself and do not use RepeatCount variable at all.
@Zemian
Ok got it. I will modify my code accordingly
Comment by Zemian Deng [ 14/Sep/11 ]
As rare the case maybe, I just want to add my opinion that as general, each trigger ought to have
an option to end it by having either an endTime or total repeatCount. To me, the repeatCount
would have just as much same value as endTime. It's a mean to stop the trigger under a
condition in regardless of the trigger type. And it's good for testing too.
Comment by James House [ 14/Sep/11 ]
@Zemian - I agree there is some value in retaining repeatCount as currently implemented, and
your other statements related to it - I just meant to say that I think it will be the more rare
usecase that an end user sets it for this type of trigger.
All - I think it will be worthwhile to provide some syntactic sugar for calculating the end time of
day given interval, time unit, and starting time of day. Let's ponder where that can best be put.
Comment by Zemian Deng [ 14/Sep/11 ]
In addition to endingDailyAt(), we could have an endingDailyWithCount(int) in the trigger
builder. I would suggest avoid the word "repeat" in this method so as not to confuse that actual
total repeatCount usage.
Comment by James House [ 14/Sep/11 ]
How about endingDailyAfterCount(int) ?
Comment by Zemian Deng [ 14/Sep/11 ]
Okay, sounds good. I will try to add this in.
Comment by Zemian Deng [ 14/Sep/11 ]
I added endingDailyAfterCount to the builder. r1666 on the 2.1.x branch.
You may see DailyTimeIntervalScheduleBuilderTest.java for usage.
I am attaching a new jar again for testing: quartz-2.1.0-rc_with_endingDailyAfterCount.jar
Comment by uday ogra [ 16/Sep/11 ]
I downloaded the latest jat and was testing it.
I found this issue (which might be due to my wrong code also):
DailyTimeIntervalScheduleBuilder schedBuilder =
DailyTimeIntervalScheduleBuilder.dailyTimeIntervalSchedule()
.withIntervalInSeconds(Integer.valueOf(interval)).withMisfireHandlingInstructionDoNothing()
.startingDailyAt(stime);
if (null != etime)
{ schedBuilder.endingDailyAt(etime); }
if (Integer.valueOf(repeat) != -1)
{ schedBuilder.endingDailyAfterCount(Integer.valueOf(repeat)); }
....
Here 'etime' is null, hence not getting set
'stime' is 14:0:0 i.e 2 PM
'repeat' is 10
'interval' is 2 minutes
So logically endTimeOfDay should be 14:18 PM
But it is getting calculated as 2:18
And I am getting error:
StartTimeOfDay TimeOfDay[14:0:0] should not come after endTimeOfDay
TimeOfDay[2:18:0]
Comment by uday ogra [ 16/Sep/11 ]
In the previous code snippet if I replace 'stime' with 2 AM instead of 2 PM, it works fine
Comment by Zemian Deng [ 16/Sep/11 ]
Hello uday,
I do see a mistake in code. I have corrected to use Calendar.HOUR_OF_DAY now. Can you
retry with the new quartz-2.1.0-rc_with_endingDailyAfterCount_2.jar?
PS:
You should know that both endingDailyAt and endingDailyAfterCount are modifying the same
field in the builder, and you should use just one. So you might want to use "else if" in your code
instead.
Comment by uday ogra [ 11/Oct/11 ]
Hi Zemian,
We downloaded the official release 2.1.0 and everything is working fine.
Its just in DailyTimeIntervalTrigger, can we have some method like
getRemainingCountOfTheDay which will basically give number of times job will be executing
more on that particular day. A sort of per day remaining count
Comment by Zemian Deng [ 11/Oct/11 ]
Hi,
A getRemainingCountOfTheDay() seems to be very specific use case. The count will also get
affected by misfired policy. I would suggest that you try writing your own TriggerListener and
keep the count on your own. If you feel this feature is important enough to benefit other users,
then feel free to file a separate FeatureRequest, and then others will get to vote.
Generated at Tue Feb 09 05:53:41 PST 2016 using JIRA 6.2.4#6261sha1:4d2e6f6f26064845673c8e7ffe9b6b84b45a6e79.
Download