-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make sure that disabled jobs are paused in Quartz #25408
Conversation
@@ -166,6 +166,7 @@ public QuartzScheduler(SchedulerContext context, QuartzSupport quartzSupport, Sc | |||
String cron = SchedulerUtils.lookUpPropertyValue(scheduled.cron()); | |||
if (!cron.isEmpty()) { | |||
if (SchedulerUtils.isOff(cron)) { | |||
this.pause(identity); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's pause the job disabled job to effectively let Quartz know that this should not be invoked in any way.
When the job is enabled/turned on, it'll be rescheduled and executed again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This results in a org.quartz.Scheduler.pauseJob(JobKey)
invocation, right? What happens if the job does not exist yet? Is it a no-op?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the job does not exists, it is a no-op.
I'll add a test case in the integration test project to make sure we won't have a regression here.
@@ -214,6 +215,7 @@ public QuartzScheduler(SchedulerContext context, QuartzSupport quartzSupport, Sc | |||
} else if (!scheduled.every().isEmpty()) { | |||
OptionalLong everyMillis = SchedulerUtils.parseEveryAsMillis(scheduled); | |||
if (!everyMillis.isPresent()) { | |||
this.pause(identity); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ruiarodrigues this should fix the issue reported in #25214. Can you have a look? |
@machi1990 What am I suppose to do/check? 😄 |
:-) You can clone my fork: https://github.com/machi1990/quarkus and checkout to the |
I cloned it but I'm having some problems with the download of the dependencies. Is there any snapshot available of your fork? |
No, I do not have a snapshot. What dependencies issue are you encountering?
This is explained in the PR description. The job is discarded and this is fine for in memory jobs but for persisted jobs quartz will try to launch them ( quarkus/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java Line 563 in ace0e89
main codebase (it might be different from the version of quarkus the reproducer is running), the trigger method annotated with @Scheduled won't be executed - previously this would have cause a NPE (issue #24931, fixed by #25407) . With just that, the @scheduled trigger will be skipped all together.Now the change in this PR really make sure that Quartz does not try to fire the trigger for disabled jobs. They'll be resumed automatically when the job is enabled / turned on again. |
From you explanation, the fix seems fine. I was able to compile finally. I let you know. |
I'm not able to run the reproducer with the 999-SNAPSHOT. I think you can go ahead and I will test it again when the final release is available |
Thanks for trying anyway. I wonder what's the issue you are facing? |
@Path("cron") | ||
@Produces(MediaType.TEXT_PLAIN) | ||
public String getCronCount() { | ||
return disabledScheduledMethods.valueSetByCronScheduledMethod; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't access a static variable like this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't give this much thought since it is a variable that's there to only show that it is not initialized.
|
||
@ApplicationScoped | ||
public class DisabledScheduledMethods { | ||
static String valueSetByCronScheduledMethod = ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we should make these variables volatile
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same reasoning as #25408 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the read access above is more a matter of style the fact that this field is not thread-safe is risky and may cause intermittent test failures or false positives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see your point. I've added the suggestion and added some comments to the methods
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I've added two minor comments about the test though...
Fixes quarkusio#25214 Disabled methods whose jobs details and triggers were already in the database were still getting triggered because Quartz invokes all the jobs in the database that are not in the paused State. This is to make sure that the disabled methods are effectively not triggered by Quartz in any way. Furthermore, I do not believe the full scheduled method implementing the Application custom logic was called because of the checks in the extensions which meant the App business logic trigger was not full invoked but pausing the triggers via Quartz we are sure that the trigger won't be invoked when it is disabled. Previously this was done via checks in the extension which mean that only the Application logic of the scheduled method was not called. - https://github.com/quarkusio/quarkus/blob/4df39b60a0b3d132713e6d60087a1054588d4a5f/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java#L215-L218 - https://github.com/quarkusio/quarkus/blob/4df39b60a0b3d132713e6d60087a1054588d4a5f/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java#L168-L170 which meant that the trigger was not stored in known business triggers at https://github.com/quarkusio/quarkus/blob/4df39b60a0b3d132713e6d60087a1054588d4a5f/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java#L302-L303 meaning that upon the execution invocation of the method in https://github.com/quarkusio/quarkus/blob/4df39b60a0b3d132713e6d60087a1054588d4a5f/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java#L560 the business logic wasn't triggered but a NPE (same as quarkusio#24931) could have been raised with the code in main branch
Thanks. Can you have a look? |
Thanks @mkouba |
Fixes #25214
Disabled methods whose jobs details and triggers were already in the
database were still getting triggered because Quartz invokes all the
jobs in the database that are not in the paused State.
This is to make sure that the disabled methods are effectively not
triggered by Quartz in any way.
Furthermore, I do not believe the full scheduled method implementing the Application custom logic
was called because of the checks in the extensions which meant the
App business logic trigger was not full invoked but pausing the triggers
via Quartz we are sure that the trigger won't be invoked when it is
disabled.
Previously this was done via checks in the extension which mean that
only the Application logic of the scheduled method was not called.
quarkus/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java
Lines 215 to 218 in 4df39b6
quarkus/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java
Lines 168 to 170 in 4df39b6
which meant that the trigger was not stored in known business triggers
at
quarkus/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java
Lines 302 to 303 in 4df39b6
meaning that upon the execution invocation of the method in
quarkus/extensions/quartz/runtime/src/main/java/io/quarkus/quartz/runtime/QuartzScheduler.java
Line 560 in 4df39b6
the business logic wasn't triggered but a NPE (same as #24931) could have been raised
with the code in main branch