Fix object graph deletion in SimpleJobRepository#deleteJobInstance

Before this commit, SimpleJobRepository#deleteJobInstance
was only deleting the given job instance and not the entire
object graph, which leads to data inconsistency (orphan job
executions and invalid foreign keys).

This commit fixes the contract and the implementation of the method
to delete the entire object graph.

Resolves #4250
This commit is contained in:
Mahmoud Ben Hassine
2023-02-20 09:57:08 +01:00
parent 4629294b65
commit 0103ef025d
4 changed files with 29 additions and 4 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2022 the original author or authors.
* Copyright 2006-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -244,7 +244,9 @@ public interface JobRepository {
}
/**
* Delete the job instance.
* Delete the job instance object graph (ie the job instance with all associated job
* executions along with their respective object graphs as specified in
* {@link #deleteJobExecution(JobExecution)}).
* @param jobInstance the job instance to delete
* @since 5.0
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2006-2022 the original author or authors.
* Copyright 2006-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -131,7 +131,8 @@ public interface JobInstanceDao {
long getJobInstanceCount(@Nullable String jobName) throws NoSuchJobException;
/**
* Delete the job instance.
* Delete the job instance. This method is not expected to delete the associated job
* executions. If this is needed, clients of this method should do that manually.
* @param jobInstance the job instance to delete
* @since 5.0
*/

View File

@@ -328,6 +328,10 @@ public class SimpleJobRepository implements JobRepository {
@Override
public void deleteJobInstance(JobInstance jobInstance) {
List<JobExecution> jobExecutions = this.jobExecutionDao.findJobExecutions(jobInstance);
for (JobExecution jobExecution : jobExecutions) {
deleteJobExecution(jobExecution);
}
this.jobInstanceDao.deleteJobInstance(jobInstance);
}

View File

@@ -366,4 +366,22 @@ class SimpleJobRepositoryTests {
verify(this.jobExecutionDao).deleteJobExecution(jobExecution);
}
@Test
void testDeleteJobInstance() {
// given
JobExecution jobExecution1 = mock(JobExecution.class);
JobExecution jobExecution2 = mock(JobExecution.class);
JobInstance jobInstance = mock(JobInstance.class);
when(this.jobExecutionDao.findJobExecutions(jobInstance))
.thenReturn(Arrays.asList(jobExecution1, jobExecution2));
// when
this.jobRepository.deleteJobInstance(jobInstance);
// then
verify(this.jobExecutionDao).deleteJobExecution(jobExecution1);
verify(this.jobExecutionDao).deleteJobExecution(jobExecution2);
verify(this.jobInstanceDao).deleteJobInstance(jobInstance);
}
}