Browse Source

Fix queryByTypeAndJobId might error due to multiple result (#15883)

3.2.2-release-bak
Wenjun Ruan 6 months ago committed by GitHub
parent
commit
e9d85914d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/TriggerRelationMapper.java
  2. 26
      dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/TriggerRelationMapperTest.java
  3. 2
      dolphinscheduler-dist/release-docs/LICENSE
  4. 4
      dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/process/TriggerRelationService.java
  5. 39
      dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/process/TriggerRelationServiceImpl.java
  6. 56
      dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/process/TriggerRelationServiceTest.java
  7. 7
      pom.xml
  8. 4
      tools/dependencies/known-dependencies.txt

2
dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/TriggerRelationMapper.java

@ -36,7 +36,7 @@ public interface TriggerRelationMapper extends BaseMapper<TriggerRelation> {
* @param jobId * @param jobId
* @return * @return
*/ */
TriggerRelation queryByTypeAndJobId(@Param("triggerType") Integer triggerType, @Param("jobId") int jobId); List<TriggerRelation> queryByTypeAndJobId(@Param("triggerType") Integer triggerType, @Param("jobId") int jobId);
/** /**
* query triggerRelation by code * query triggerRelation by code

26
dolphinscheduler-dao/src/test/java/org/apache/dolphinscheduler/dao/mapper/TriggerRelationMapperTest.java

@ -17,13 +17,13 @@
package org.apache.dolphinscheduler.dao.mapper; package org.apache.dolphinscheduler.dao.mapper;
import static com.google.common.truth.Truth.assertThat;
import org.apache.dolphinscheduler.common.enums.ApiTriggerType; import org.apache.dolphinscheduler.common.enums.ApiTriggerType;
import org.apache.dolphinscheduler.common.utils.DateUtils; import org.apache.dolphinscheduler.common.utils.DateUtils;
import org.apache.dolphinscheduler.dao.BaseDaoTest; import org.apache.dolphinscheduler.dao.BaseDaoTest;
import org.apache.dolphinscheduler.dao.entity.TriggerRelation; import org.apache.dolphinscheduler.dao.entity.TriggerRelation;
import java.util.List;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -67,9 +67,9 @@ public class TriggerRelationMapperTest extends BaseDaoTest {
@Test @Test
public void testQueryByTypeAndJobId() { public void testQueryByTypeAndJobId() {
TriggerRelation expectRelation = createTriggerRelation(); TriggerRelation expectRelation = createTriggerRelation();
TriggerRelation actualRelation = triggerRelationMapper.queryByTypeAndJobId( assertThat(
expectRelation.getTriggerType(), expectRelation.getJobId()); triggerRelationMapper.queryByTypeAndJobId(expectRelation.getTriggerType(), expectRelation.getJobId()))
Assertions.assertEquals(expectRelation, actualRelation); .containsExactly(expectRelation);
} }
/** /**
@ -80,9 +80,8 @@ public class TriggerRelationMapperTest extends BaseDaoTest {
@Test @Test
public void testQueryByTriggerRelationCode() { public void testQueryByTriggerRelationCode() {
TriggerRelation expectRelation = createTriggerRelation(); TriggerRelation expectRelation = createTriggerRelation();
List<TriggerRelation> actualRelations = triggerRelationMapper.queryByTriggerRelationCode( assertThat(triggerRelationMapper.queryByTriggerRelationCode(expectRelation.getTriggerCode()))
expectRelation.getTriggerCode()); .containsExactly(expectRelation);
Assertions.assertEquals(actualRelations.size(), 1);
} }
/** /**
@ -93,17 +92,15 @@ public class TriggerRelationMapperTest extends BaseDaoTest {
@Test @Test
public void testQueryByTriggerRelationCodeAndType() { public void testQueryByTriggerRelationCodeAndType() {
TriggerRelation expectRelation = createTriggerRelation(); TriggerRelation expectRelation = createTriggerRelation();
List<TriggerRelation> actualRelations = triggerRelationMapper.queryByTriggerRelationCodeAndType( assertThat(triggerRelationMapper.queryByTriggerRelationCodeAndType(expectRelation.getTriggerCode(),
expectRelation.getTriggerCode(), expectRelation.getTriggerType()); expectRelation.getTriggerType())).containsExactly(expectRelation);
Assertions.assertEquals(actualRelations.size(), 1);
} }
@Test @Test
public void testUpsert() { public void testUpsert() {
TriggerRelation expectRelation = createTriggerRelation(); TriggerRelation expectRelation = createTriggerRelation();
triggerRelationMapper.upsert(expectRelation); triggerRelationMapper.upsert(expectRelation);
TriggerRelation actualRelation = triggerRelationMapper.selectById(expectRelation.getId()); assertThat(triggerRelationMapper.selectById(expectRelation.getId())).isEqualTo(expectRelation);
Assertions.assertEquals(expectRelation, actualRelation);
} }
/** /**
@ -113,8 +110,7 @@ public class TriggerRelationMapperTest extends BaseDaoTest {
public void testDelete() { public void testDelete() {
TriggerRelation expectRelation = createTriggerRelation(); TriggerRelation expectRelation = createTriggerRelation();
triggerRelationMapper.deleteById(expectRelation.getId()); triggerRelationMapper.deleteById(expectRelation.getId());
TriggerRelation actualRelation = triggerRelationMapper.selectById(expectRelation.getId()); assertThat(triggerRelationMapper.selectById(expectRelation.getId())).isNull();
Assertions.assertNull(actualRelation);
} }
/** /**

2
dolphinscheduler-dist/release-docs/LICENSE vendored

@ -528,7 +528,7 @@ The text of each license is also included at licenses/LICENSE-[project].txt.
nimbus-jose-jwt 9.22: https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt/9.22, Apache 2.0 nimbus-jose-jwt 9.22: https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt/9.22, Apache 2.0
woodstox-core 6.4.0: https://mvnrepository.com/artifact/com.fasterxml.woodstox/woodstox-core/6.4.0, Apache 2.0 woodstox-core 6.4.0: https://mvnrepository.com/artifact/com.fasterxml.woodstox/woodstox-core/6.4.0, Apache 2.0
auto-value 1.10.1: https://mvnrepository.com/artifact/com.google.auto.value/auto-value/1.10.1, Apache 2.0 auto-value 1.10.1: https://mvnrepository.com/artifact/com.google.auto.value/auto-value/1.10.1, Apache 2.0
auto-value-annotations 1.10.1: https://mvnrepository.com/artifact/com.google.auto.value/auto-value-annotations/1.10.1, Apache 2.0 auto-value-annotations 1.10.4: https://mvnrepository.com/artifact/com.google.auto.value/auto-value-annotations/1.10.4, Apache 2.0
conscrypt-openjdk-uber 2.5.2: https://mvnrepository.com/artifact/org.conscrypt/conscrypt-openjdk-uber/2.5.2, Apache 2.0 conscrypt-openjdk-uber 2.5.2: https://mvnrepository.com/artifact/org.conscrypt/conscrypt-openjdk-uber/2.5.2, Apache 2.0
gapic-google-cloud-storage-v2 2.18.0-alpha: https://mvnrepository.com/artifact/com.google.api.grpc/gapic-google-cloud-storage-v2/2.18.0-alpha, Apache 2.0 gapic-google-cloud-storage-v2 2.18.0-alpha: https://mvnrepository.com/artifact/com.google.api.grpc/gapic-google-cloud-storage-v2/2.18.0-alpha, Apache 2.0
google-api-client 2.2.0: https://mvnrepository.com/artifact/com.google.api-client/google-api-client/2.2.0, Apache 2.0 google-api-client 2.2.0: https://mvnrepository.com/artifact/com.google.api-client/google-api-client/2.2.0, Apache 2.0

4
dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/process/TriggerRelationService.java

@ -20,6 +20,8 @@ package org.apache.dolphinscheduler.service.process;
import org.apache.dolphinscheduler.common.enums.ApiTriggerType; import org.apache.dolphinscheduler.common.enums.ApiTriggerType;
import org.apache.dolphinscheduler.dao.entity.TriggerRelation; import org.apache.dolphinscheduler.dao.entity.TriggerRelation;
import java.util.List;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** /**
@ -30,7 +32,7 @@ public interface TriggerRelationService {
void saveTriggerToDb(ApiTriggerType type, Long triggerCode, Integer jobId); void saveTriggerToDb(ApiTriggerType type, Long triggerCode, Integer jobId);
TriggerRelation queryByTypeAndJobId(ApiTriggerType apiTriggerType, int jobId); List<TriggerRelation> queryByTypeAndJobId(ApiTriggerType apiTriggerType, int jobId);
int saveCommandTrigger(Integer commandId, Integer processInstanceId); int saveCommandTrigger(Integer commandId, Integer processInstanceId);

39
dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/process/TriggerRelationServiceImpl.java

@ -21,7 +21,12 @@ import org.apache.dolphinscheduler.common.enums.ApiTriggerType;
import org.apache.dolphinscheduler.dao.entity.TriggerRelation; import org.apache.dolphinscheduler.dao.entity.TriggerRelation;
import org.apache.dolphinscheduler.dao.mapper.TriggerRelationMapper; import org.apache.dolphinscheduler.dao.mapper.TriggerRelationMapper;
import org.apache.commons.collections4.CollectionUtils;
import java.util.Date; import java.util.Date;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -29,6 +34,7 @@ import org.springframework.stereotype.Component;
/** /**
* Trigger relation operator to db * Trigger relation operator to db
*/ */
@Slf4j
@Component @Component
public class TriggerRelationServiceImpl implements TriggerRelationService { public class TriggerRelationServiceImpl implements TriggerRelationService {
@ -45,29 +51,44 @@ public class TriggerRelationServiceImpl implements TriggerRelationService {
triggerRelation.setUpdateTime(new Date()); triggerRelation.setUpdateTime(new Date());
triggerRelationMapper.upsert(triggerRelation); triggerRelationMapper.upsert(triggerRelation);
} }
@Override @Override
public TriggerRelation queryByTypeAndJobId(ApiTriggerType apiTriggerType, int jobId) { public List<TriggerRelation> queryByTypeAndJobId(ApiTriggerType apiTriggerType, int jobId) {
return triggerRelationMapper.queryByTypeAndJobId(apiTriggerType.getCode(), jobId); return triggerRelationMapper.queryByTypeAndJobId(apiTriggerType.getCode(), jobId);
} }
@Override @Override
public int saveCommandTrigger(Integer commandId, Integer processInstanceId) { public int saveCommandTrigger(Integer commandId, Integer processInstanceId) {
TriggerRelation exist = queryByTypeAndJobId(ApiTriggerType.PROCESS, processInstanceId); List<TriggerRelation> existTriggers = queryByTypeAndJobId(ApiTriggerType.PROCESS, processInstanceId);
if (exist == null) { if (CollectionUtils.isEmpty(existTriggers)) {
return 0; return 0;
} }
saveTriggerToDb(ApiTriggerType.COMMAND, exist.getTriggerCode(), commandId); existTriggers.forEach(triggerRelation -> saveTriggerToDb(ApiTriggerType.COMMAND,
return 1; triggerRelation.getTriggerCode(), commandId));
int triggerRelationSize = existTriggers.size();
if (triggerRelationSize > 1) {
// Fix https://github.com/apache/dolphinscheduler/issues/15864
// This case shouldn't happen
log.error("The PROCESS TriggerRelation of command: {} is more than one", commandId);
}
return existTriggers.size();
} }
@Override @Override
public int saveProcessInstanceTrigger(Integer commandId, Integer processInstanceId) { public int saveProcessInstanceTrigger(Integer commandId, Integer processInstanceId) {
TriggerRelation exist = queryByTypeAndJobId(ApiTriggerType.COMMAND, commandId); List<TriggerRelation> existTriggers = queryByTypeAndJobId(ApiTriggerType.COMMAND, commandId);
if (exist == null) { if (CollectionUtils.isEmpty(existTriggers)) {
return 0; return 0;
} }
saveTriggerToDb(ApiTriggerType.PROCESS, exist.getTriggerCode(), processInstanceId); existTriggers.forEach(triggerRelation -> saveTriggerToDb(ApiTriggerType.PROCESS,
return 1; triggerRelation.getTriggerCode(), processInstanceId));
int triggerRelationSize = existTriggers.size();
if (triggerRelationSize > 1) {
// Fix https://github.com/apache/dolphinscheduler/issues/15864
// This case shouldn't happen
log.error("The COMMAND TriggerRelation of command: {} is more than one", commandId);
}
return existTriggers.size();
} }
} }

56
dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/process/TriggerRelationServiceTest.java

@ -17,24 +17,26 @@
package org.apache.dolphinscheduler.service.process; package org.apache.dolphinscheduler.service.process;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import org.apache.dolphinscheduler.common.enums.ApiTriggerType; import org.apache.dolphinscheduler.common.enums.ApiTriggerType;
import org.apache.dolphinscheduler.dao.entity.TriggerRelation; import org.apache.dolphinscheduler.dao.entity.TriggerRelation;
import org.apache.dolphinscheduler.dao.mapper.TriggerRelationMapper; import org.apache.dolphinscheduler.dao.mapper.TriggerRelationMapper;
import org.apache.dolphinscheduler.service.cron.CronUtilsTest;
import java.util.Date; import java.util.Date;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness; import org.mockito.quality.Strictness;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.google.common.collect.Lists;
/** /**
* Trigger Relation Service Test * Trigger Relation Service Test
@ -43,8 +45,6 @@ import org.slf4j.LoggerFactory;
@MockitoSettings(strictness = Strictness.LENIENT) @MockitoSettings(strictness = Strictness.LENIENT)
public class TriggerRelationServiceTest { public class TriggerRelationServiceTest {
private static final Logger logger = LoggerFactory.getLogger(CronUtilsTest.class);
@InjectMocks @InjectMocks
private TriggerRelationServiceImpl triggerRelationService; private TriggerRelationServiceImpl triggerRelationService;
@Mock @Mock
@ -52,47 +52,37 @@ public class TriggerRelationServiceTest {
@Test @Test
public void saveTriggerToDb() { public void saveTriggerToDb() {
Mockito.doNothing().when(triggerRelationMapper).upsert(Mockito.any()); doNothing().when(triggerRelationMapper).upsert(any());
triggerRelationService.saveTriggerToDb(ApiTriggerType.COMMAND, 1234567890L, 100); triggerRelationService.saveTriggerToDb(ApiTriggerType.COMMAND, 1234567890L, 100);
} }
@Test @Test
public void queryByTypeAndJobId() { public void queryByTypeAndJobId() {
Mockito.doNothing().when(triggerRelationMapper).upsert(Mockito.any()); doNothing().when(triggerRelationMapper).upsert(any());
Mockito.when(triggerRelationMapper.queryByTypeAndJobId(ApiTriggerType.PROCESS.getCode(), 100)) when(triggerRelationMapper.queryByTypeAndJobId(ApiTriggerType.PROCESS.getCode(), 100))
.thenReturn(getTriggerTdoDb()); .thenReturn(Lists.newArrayList(getTriggerTdoDb()));
TriggerRelation triggerRelation1 = triggerRelationService.queryByTypeAndJobId( assertThat(triggerRelationService.queryByTypeAndJobId(ApiTriggerType.PROCESS, 100)).hasSize(1);
ApiTriggerType.PROCESS, 100); assertThat(triggerRelationService.queryByTypeAndJobId(ApiTriggerType.PROCESS, 200)).isEmpty();
Assertions.assertNotNull(triggerRelation1);
TriggerRelation triggerRelation2 = triggerRelationService.queryByTypeAndJobId(
ApiTriggerType.PROCESS, 200);
Assertions.assertNull(triggerRelation2);
} }
@Test @Test
public void saveCommandTrigger() { public void saveCommandTrigger() {
Mockito.doNothing().when(triggerRelationMapper).upsert(Mockito.any()); doNothing().when(triggerRelationMapper).upsert(any());
Mockito.when(triggerRelationMapper.queryByTypeAndJobId(ApiTriggerType.PROCESS.getCode(), 100)) when(triggerRelationMapper.queryByTypeAndJobId(ApiTriggerType.PROCESS.getCode(), 100))
.thenReturn(getTriggerTdoDb()); .thenReturn(Lists.newArrayList(getTriggerTdoDb()));
int result = -1; assertThat(triggerRelationService.saveCommandTrigger(1234567890, 100)).isAtLeast(1);
result = triggerRelationService.saveCommandTrigger(1234567890, 100); assertThat(triggerRelationService.saveCommandTrigger(1234567890, 200)).isEqualTo(0);
Assertions.assertTrue(result > 0);
result = triggerRelationService.saveCommandTrigger(1234567890, 200);
Assertions.assertTrue(result == 0);
} }
@Test @Test
public void saveProcessInstanceTrigger() { public void saveProcessInstanceTrigger() {
Mockito.doNothing().when(triggerRelationMapper).upsert(Mockito.any()); doNothing().when(triggerRelationMapper).upsert(any());
Mockito.when(triggerRelationMapper.queryByTypeAndJobId(ApiTriggerType.COMMAND.getCode(), 100)) when(triggerRelationMapper.queryByTypeAndJobId(ApiTriggerType.COMMAND.getCode(), 100))
.thenReturn(getTriggerTdoDb()); .thenReturn(Lists.newArrayList(getTriggerTdoDb()));
int result = -1; assertThat(triggerRelationService.saveProcessInstanceTrigger(100, 1234567890)).isAtLeast(1);
result = triggerRelationService.saveProcessInstanceTrigger(100, 1234567890); assertThat(triggerRelationService.saveProcessInstanceTrigger(200, 1234567890)).isEqualTo(0);
Assertions.assertTrue(result > 0);
result = triggerRelationService.saveProcessInstanceTrigger(200, 1234567890);
Assertions.assertTrue(result == 0);
} }
private TriggerRelation getTriggerTdoDb() { private TriggerRelation getTriggerTdoDb() {

7
pom.xml

@ -89,6 +89,7 @@
<owasp-dependency-check-maven.version>7.1.2</owasp-dependency-check-maven.version> <owasp-dependency-check-maven.version>7.1.2</owasp-dependency-check-maven.version>
<lombok.version>1.18.20</lombok.version> <lombok.version>1.18.20</lombok.version>
<awaitility.version>4.2.0</awaitility.version> <awaitility.version>4.2.0</awaitility.version>
<truth.version>1.4.2</truth.version>
<docker.hub>apache</docker.hub> <docker.hub>apache</docker.hub>
<docker.repo>${project.name}</docker.repo> <docker.repo>${project.name}</docker.repo>
<docker.tag>${project.version}</docker.tag> <docker.tag>${project.version}</docker.tag>
@ -372,6 +373,12 @@
<version>${awaitility.version}</version> <version>${awaitility.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<version>${truth.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

4
tools/dependencies/known-dependencies.txt

@ -9,7 +9,7 @@ animal-sniffer-annotations-1.19.jar
annotations-2.17.282.jar annotations-2.17.282.jar
annotations-13.0.jar annotations-13.0.jar
apache-client-2.17.282.jar apache-client-2.17.282.jar
asm-9.1.jar asm-9.6.jar
aspectjweaver-1.9.7.jar aspectjweaver-1.9.7.jar
aspectjrt-1.9.7.jar aspectjrt-1.9.7.jar
auth-2.17.282.jar auth-2.17.282.jar
@ -434,7 +434,7 @@ woodstox-core-6.4.0.jar
azure-core-management-1.10.1.jar azure-core-management-1.10.1.jar
api-common-2.6.0.jar api-common-2.6.0.jar
auto-value-1.10.1.jar auto-value-1.10.1.jar
auto-value-annotations-1.10.1.jar auto-value-annotations-1.10.4.jar
bcpkix-jdk15on-1.67.jar bcpkix-jdk15on-1.67.jar
bcprov-jdk15on-1.67.jar bcprov-jdk15on-1.67.jar
conscrypt-openjdk-uber-2.5.2.jar conscrypt-openjdk-uber-2.5.2.jar

Loading…
Cancel
Save