Skip to content
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

Quartz - fix job refire behavior, improve dep. bean job scenario #42223

Merged
merged 2 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ public void testDependentBeanJobDestroyed() throws SchedulerException, Interrupt

@Test
public void testDependentBeanJobWithRefire() throws SchedulerException, InterruptedException {
// 5 one-off jobs should trigger construction/execution/destruction 10 times in total
CountDownLatch execLatch = service.initExecuteLatch(10);
CountDownLatch constructLatch = service.initConstructLatch(10);
CountDownLatch destroyedLatch = service.initDestroyedLatch(10);
// 5 one-off jobs should trigger construction/execution/destruction 5 times in total
CountDownLatch execLatch = service.initExecuteLatch(5);
CountDownLatch constructLatch = service.initConstructLatch(5);
CountDownLatch destroyedLatch = service.initDestroyedLatch(5);
for (int i = 0; i < 5; i++) {
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger" + i, "myRefiringGroup")
Expand All @@ -104,10 +104,10 @@ public void testDependentBeanJobWithRefire() throws SchedulerException, Interrup
assertTrue(constructLatch.await(2, TimeUnit.SECONDS), "Latch count: " + constructLatch.getCount());
assertTrue(destroyedLatch.await(2, TimeUnit.SECONDS), "Latch count: " + destroyedLatch.getCount());

// repeating job triggering three times; we expect six beans to exist for that due to refires
execLatch = service.initExecuteLatch(6);
constructLatch = service.initConstructLatch(6);
destroyedLatch = service.initDestroyedLatch(6);
// repeating job triggering three times; re-fires should NOT recreate the bean instance
execLatch = service.initExecuteLatch(3);
constructLatch = service.initConstructLatch(3);
destroyedLatch = service.initDestroyedLatch(3);
JobDetail job = JobBuilder.newJob(RefiringJob.class)
.withIdentity("myRepeatingJob", "myRefiringGroup")
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

Expand Down Expand Up @@ -40,6 +41,7 @@ public class InterruptableJobTest {

static final CountDownLatch INTERRUPT_LATCH = new CountDownLatch(1);
static final CountDownLatch EXECUTE_LATCH = new CountDownLatch(1);
static Integer initCounter = 0;

static final CountDownLatch NON_INTERRUPTABLE_EXECUTE_LATCH = new CountDownLatch(1);
static final CountDownLatch NON_INTERRUPTABLE_HOLD_LATCH = new CountDownLatch(1);
Expand All @@ -66,7 +68,9 @@ public void testInterruptableJob() throws InterruptedException {
throw new RuntimeException(e);
}

assertTrue(INTERRUPT_LATCH.await(5, TimeUnit.SECONDS));
assertTrue(INTERRUPT_LATCH.await(3, TimeUnit.SECONDS));
// asserts that a single dep. scoped bean instance was used for both, execute() and interrupt() methods
assertTrue(initCounter == 1);
}

@Test
Expand Down Expand Up @@ -102,6 +106,11 @@ public void testNonInterruptableJob() throws InterruptedException {
@ApplicationScoped
static class MyJob implements InterruptableJob {

@PostConstruct
public void postConstruct() {
initCounter++;
}

@Override
public void execute(JobExecutionContext context) {
EXECUTE_LATCH.countDown();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,34 @@
*/
class CdiAwareJob implements InterruptableJob {

private final Instance<? extends Job> jobInstance;
private final Instance.Handle<? extends Job> handle;
private final Job beanInstance;

public CdiAwareJob(Instance<? extends Job> jobInstance) {
this.jobInstance = jobInstance;
public CdiAwareJob(Instance.Handle<? extends Job> handle) {
this.handle = handle;
this.beanInstance = handle.get();
}

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
Instance.Handle<? extends Job> handle = jobInstance.getHandle();
boolean refire = false;
try {
handle.get().execute(context);
beanInstance.execute(context);
} catch (JobExecutionException e) {
refire = e.refireImmediately();
throw e;
} finally {
if (handle.getBean().getScope().equals(Dependent.class)) {
if (refire != true && handle.getBean().getScope().equals(Dependent.class)) {
handle.destroy();
}
}
}

@Override
public void interrupt() throws UnableToInterruptJobException {
Instance.Handle<? extends Job> handle = jobInstance.getHandle();
// delegate if possible; throw an exception in other cases
if (InterruptableJob.class.isAssignableFrom(handle.getBean().getBeanClass())) {
try {
((InterruptableJob) handle.get()).interrupt();
} finally {
if (handle.getBean().getScope().equals(Dependent.class)) {
handle.destroy();
}
}
((InterruptableJob) beanInstance).interrupt();
} else {
throw new UnableToInterruptJobException("Job " + handle.getBean().getBeanClass()
+ " can not be interrupted, since it does not implement " + InterruptableJob.class.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,7 @@ public Job newJob(TriggerFiredBundle bundle, org.quartz.Scheduler Scheduler) thr
Instance<? extends Job> instance = jobs.select(jobClass);
if (instance.isResolvable()) {
// This is a job backed by a CDI bean
return jobWithSpanWrapper(new CdiAwareJob(instance));
return jobWithSpanWrapper(new CdiAwareJob(instance.getHandle()));
}
// Instantiate a plain job class
return jobWithSpanWrapper(super.newJob(bundle, Scheduler));
Expand Down