Commit f8beddff authored by Kristel Meikas's avatar Kristel Meikas
Browse files

Merge branch 'develop' into 'master'

Release: merge 'develop' into 'master' created by Kristel Meikas

See merge request teis/scheduler-service!30
parents dc98dddf 1660abf9
# Changelog
## [1.15.0] - 2021-03-22
* TEIS-1566: Introduced @BpmProcess annotation which maps RequestMetaDto for logging and security context via
RabbitListenerAspect
## [1.14.0] - 2021-03-08
* NB: replaced Gradle compile with implementation which doesn't expose service libraries to depending services. Services
which depend on latest versions of scheduler-service-lib may require to add dependencies for Gradle task
integTestImplementation in service Gradle configuration
## [1.13.0] - 2021-01-22
* added integration tests
## [1.12.0] - 2020-10-30
......
theGroup=ee.sm.ti.teis
theVersion=1.14.0
commonsVersion=1.21.0
commonApiGatewayVersion=1.21.0
theVersion=1.15.0
commonsVersion=1.22.0
commonApiGatewayVersion=1.22.0
adminApiGatewayVersion=1.11.0
pluginVersion=1.2.0
pluginVersion=1.3.0
......@@ -15,17 +15,19 @@ dependencies {
implementation "ee.sm.ti.teis:service-request-lib:${commonsVersion}"
implementation "ee.sm.ti.teis:service-common-lib:${commonsVersion}"
implementation "ee.sm.ti.teis:admin-api-gateway-lib:${adminApiGatewayVersion}"
implementation "ee.sm.ti.teis:bpm-lib:${commonsVersion}"
implementation 'org.springframework.boot:spring-boot-starter-quartz:2.3.4.RELEASE'
testImplementation "org.camunda.bpm.extension.mockito:camunda-bpm-mockito:4.10.0"
integTestImplementation "ee.sm.ti.teis:service-request-lib:${commonsVersion}"
integTestImplementation "ee.sm.ti.teis:service-common-lib:${commonsVersion}"
integTestImplementation "ee.sm.ti.teis:admin-api-gateway-lib:${adminApiGatewayVersion}"
implementation 'org.springframework.boot:spring-boot-starter-quartz:2.3.4.RELEASE'
integTestImplementation "ee.sm.ti.teis:bpm-lib:${commonsVersion}"
integTestImplementation 'org.springframework.boot:spring-boot-starter-quartz:2.3.4.RELEASE'
integTestImplementation 'org.camunda.bpm.springboot:camunda-bpm-spring-boot-starter-webapp:3.2.1'
testImplementation "org.camunda.bpm.extension.mockito:camunda-bpm-mockito:4.10.0"
}
// Define the main class for the application
......
......@@ -17,10 +17,17 @@ import org.springframework.beans.factory.annotation.Autowired;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import static ee.sm.ti.teis.servicerequest.UserType.SYSTEM;
import static java.util.UUID.randomUUID;
import static org.assertj.core.api.Assertions.assertThat;
public class SystemJobEventsListenerTest extends SchedulerAppTestBase {
private static final RequestMetaDTO SYSTEM_REQUEST_META_DTO = RequestMetaDTO.builder()
.requestId(randomUUID().toString())
.userType(SYSTEM)
.build();
private static final String JOB_ID = "scheduler.test";
@Autowired
......@@ -38,7 +45,7 @@ public class SystemJobEventsListenerTest extends SchedulerAppTestBase {
@Test
public void sendStartedEvent_success() throws InterruptedException {
// launch job
SystemJob systemJob = jobLauncherService.launchJob(JOB_ID);
SystemJob systemJob = jobLauncherService.launchJob(JOB_ID, SYSTEM_REQUEST_META_DTO);
JobDefinitionEntity jobDefinitionEntity = jobDefinitionService.getJob(JOB_ID);
assertThat(jobDefinitionEntity.getStatus()).isEqualTo(SystemJobStatus.STARTING);
JobExecutionEntity jobExecutionEntity = executionService.getExecution(systemJob.getExecutionId());
......@@ -49,7 +56,7 @@ public class SystemJobEventsListenerTest extends SchedulerAppTestBase {
SystemJobStartedRequest request = new SystemJobStartedRequest();
request.setPayload(systemJob, RequestMetaDTO.builder().build());
systemJobEventsListener.jobStarted(request);
TimeUnit.SECONDS.sleep(1l);
TimeUnit.SECONDS.sleep(1L);
// verify started status
jobDefinitionEntity = jobDefinitionService.getJob(JOB_ID);
......@@ -61,10 +68,10 @@ public class SystemJobEventsListenerTest extends SchedulerAppTestBase {
systemJob.setFinishedAt(LocalDateTime.now());
systemJob.setResponseCode(SystemJobResponseCode.SUCCESS);
systemJob.setResponseMessage("OK");
SystemJobFinishedRequest finsihedRequest = new SystemJobFinishedRequest();
finsihedRequest.setPayload(systemJob, RequestMetaDTO.builder().build());
systemJobEventsListener.jobFinished(finsihedRequest);
TimeUnit.SECONDS.sleep(1l);
SystemJobFinishedRequest finishedRequest = new SystemJobFinishedRequest();
finishedRequest.setPayload(systemJob, RequestMetaDTO.builder().build());
systemJobEventsListener.jobFinished(finishedRequest);
TimeUnit.SECONDS.sleep(1L);
// verify finished status
jobDefinitionEntity = jobDefinitionService.getJob(JOB_ID);
......
......@@ -11,6 +11,7 @@ import ee.sm.ti.teis.scheduler.job.execution.JobExecutionEntity;
import ee.sm.ti.teis.scheduler.job.execution.JobExecutionMapper;
import ee.sm.ti.teis.scheduler.job.execution.JobExecutionRepository;
import ee.sm.ti.teis.scheduler.processor.JobLauncherService;
import ee.sm.ti.teis.servicerequest.RequestMetaDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
......@@ -26,11 +27,11 @@ public class AdminBusinessService {
private final JobDefinitionRepository jobDefinitionRepository;
private final JobDefinitionMapper jobDefinitionMapper;
public void startSystemJob(String jobId) {
public void startSystemJob(String jobId, RequestMetaDTO requestMetaDTO) {
if (jobLauncherService.isAnyProcessRunning(jobId)) {
throw new TeisBusinessException(SystemjobErrorCode.JOB_ALREADY_STARTED, "The process is already running. JobId=" + jobId);
}
jobLauncherService.launchJob(jobId);
jobLauncherService.launchJob(jobId, requestMetaDTO);
}
public List<JobExecutionDto> getSystemJobExecutions(String jobId) {
......
......@@ -18,9 +18,11 @@ public class AdminJobListener {
@RabbitListener(queues = {QueueConfig.GW_START_ADMIN_JOB})
@PreAuthorize("@accessController.hasAnyPrivilege({'TI_MANAGE_SYSTEM_JOBS'}, null, null, null)")
public StartSystemJobResponse jobStarted(StartSystemJobRequest request) {
adminBusinessService.startSystemJob(request.getPayload());
adminBusinessService.startSystemJob(request.getPayload(), request.getRequestMetaDTO());
StartSystemJobResponse response = new StartSystemJobResponse();
response.setPayload(SystemJobDto.builder().id(request.getPayload()).build(), request.getRequestMetaDTO());
return response;
}
......@@ -28,8 +30,10 @@ public class AdminJobListener {
@PreAuthorize("@accessController.hasAnyPrivilege({'TI_MANAGE_SYSTEM_JOBS'}, null, null, null)")
public GetSystemJobsResponse getSystemJobExecutions(GetSystemJobsRequest request) {
List<JobExecutionDto> systemJobExecutions = adminBusinessService.getSystemJobExecutions(request.getPayload());
GetSystemJobsResponse response = new GetSystemJobsResponse();
response.setPayload(systemJobExecutions, request.getRequestMetaDTO());
return response;
}
......@@ -37,8 +41,10 @@ public class AdminJobListener {
@PreAuthorize("@accessController.hasOfficialPrivilege({'TI_VIEW_SYSTEM_JOBS'})")
public GetSystemJobDefinitionsResponse getSystemJobDefinitions(GetSystemJobDefinitionsRequest request) {
List<JobDefinitionDto> systemJobExecutions = adminBusinessService.getSystemJobs();
GetSystemJobDefinitionsResponse response = new GetSystemJobDefinitionsResponse();
response.setPayload(systemJobExecutions, request.getRequestMetaDTO());
return response;
}
......
package ee.sm.ti.teis.scheduler.processor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import ee.sm.ti.teis.exceptions.TeisBusinessException;
import ee.sm.ti.teis.exceptions.TeisIllegalArgumentException;
import ee.sm.ti.teis.scheduler.domain.SystemJob;
import ee.sm.ti.teis.scheduler.job.definition.JobDefinitionEntity;
import ee.sm.ti.teis.scheduler.job.definition.JobDefinitionService;
import ee.sm.ti.teis.servicerequest.RequestMetaDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.RuntimeService;
......@@ -16,6 +20,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import static ee.sm.ti.teis.errors.CommonErrorCode.SYSTEM_ERROR;
import static ee.sm.ti.teis.scheduler.processor.bpm.JobProcessInstanceContext.*;
@Service
......@@ -26,12 +31,13 @@ public class JobLauncherService {
private final RuntimeService camundaRuntimeService;
private final JobDefinitionService jobDefinitionService;
private final ObjectMapper objectMapper;
@Retryable(
value = {TeisIllegalArgumentException.class},
maxAttempts = 10,
backoff = @Backoff(delay = 2000))
public SystemJob launchJob(String jobId) {
public SystemJob launchJob(String jobId, RequestMetaDTO requestMetaDTO) {
log.debug("Try to launch job. JobId={}", jobId);
if (isAnyProcessRunning(jobId)) {
......@@ -52,6 +58,11 @@ public class JobLauncherService {
Map<String, Object> instanceVariables = new HashMap<>();
instanceVariables.put(SYSTEM_JOB_VARIABLE_NAME, systemJob);
try {
instanceVariables.put(REQUEST_META_DTO, objectMapper.writeValueAsString(requestMetaDTO));
} catch (JsonProcessingException e) {
throw new TeisBusinessException(SYSTEM_ERROR, "Error serializing RequestMetaDTO into JSON format");
}
camundaRuntimeService.startProcessInstanceByMessage(EXECUTE_JOB_MESSAGE_ID,
getProcessInstanceBusinessKey(jobId, executionId.toString()), instanceVariables);
return systemJob;
......
package ee.sm.ti.teis.scheduler.processor;
import ee.sm.ti.teis.servicerequest.RequestMetaDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import static ee.sm.ti.teis.servicerequest.UserType.SYSTEM;
import static java.util.UUID.randomUUID;
@Component
@Slf4j
@RequiredArgsConstructor
public class ScheduledJobLauncher extends QuartzJobBean {
private static final RequestMetaDTO SYSTEM_REQUEST_META_DTO = RequestMetaDTO.builder()
.requestId(randomUUID().toString())
.userType(SYSTEM)
.build();
private final JobLauncherService jobLauncherService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
log.info("Launch Job with jobId='{}'", jobExecutionContext.getJobDetail().getKey());
jobLauncherService.launchJob(jobExecutionContext.getJobDetail().getKey().getName());
jobLauncherService.launchJob(jobExecutionContext.getJobDetail().getKey().getName(), SYSTEM_REQUEST_META_DTO);
}
}
package ee.sm.ti.teis.scheduler.processor.bpm;
import ee.sm.ti.teis.bpm.BpmProcess;
import ee.sm.ti.teis.scheduler.domain.SystemJob;
import ee.sm.ti.teis.scheduler.processor.JobProcessingService;
import lombok.extern.slf4j.Slf4j;
......@@ -19,6 +20,7 @@ public class JobExecutionTimeoutExceptionTaskService implements JavaDelegate {
this.jobProcessingService = jobProcessingService;
}
@BpmProcess
@Override
public void execute(DelegateExecution execution) {
String businessKey = execution.getBusinessKey();
......
package ee.sm.ti.teis.scheduler.processor.bpm;
import ee.sm.ti.teis.bpm.BpmProcess;
import ee.sm.ti.teis.scheduler.domain.SystemJob;
import ee.sm.ti.teis.scheduler.processor.JobProcessingService;
import lombok.RequiredArgsConstructor;
......@@ -17,6 +18,7 @@ public class JobFinishedTaskService implements JavaDelegate {
private final JobProcessingService jobProcessingService;
@BpmProcess
@Override
public void execute(DelegateExecution execution) {
String businessKey = execution.getBusinessKey();
......
......@@ -9,6 +9,7 @@ public class JobProcessInstanceContext {
public static final String JOB_STARTED_MESSAGE_ID = "jobStarted";
public static final String JOB_FINISHED_MESSAGE_ID = "jobFinished";
public static final String PROCESS_INSTANCE_BUSINESS_KEY_SEPARATOR = "::";
public static final String REQUEST_META_DTO = "requestMetaDto";
private JobProcessInstanceContext() {
throw new IllegalArgumentException("Utility class");
......
package ee.sm.ti.teis.scheduler.processor.bpm;
import ee.sm.ti.teis.bpm.BpmProcess;
import ee.sm.ti.teis.scheduler.domain.SystemJob;
import ee.sm.ti.teis.scheduler.processor.JobProcessingService;
import lombok.RequiredArgsConstructor;
......@@ -16,6 +17,7 @@ import static ee.sm.ti.teis.scheduler.processor.bpm.JobProcessInstanceContext.SY
public class JobStartedTaskService implements JavaDelegate {
private final JobProcessingService jobProcessingService;
@BpmProcess
@Override
public void execute(DelegateExecution execution) {
String businessKey = execution.getBusinessKey();
......
package ee.sm.ti.teis.scheduler.processor.bpm;
import ee.sm.ti.teis.bpm.BpmProcess;
import ee.sm.ti.teis.scheduler.domain.SystemJob;
import ee.sm.ti.teis.scheduler.processor.JobProcessingService;
import lombok.RequiredArgsConstructor;
......@@ -17,6 +18,7 @@ public class StartJobTaskService implements JavaDelegate {
private final JobProcessingService jobProcessingService;
@BpmProcess
@Override
public void execute(DelegateExecution execution) {
String businessKey = execution.getBusinessKey();
......
package ee.sm.ti.teis.scheduler.processor;
import com.fasterxml.jackson.databind.ObjectMapper;
import ee.sm.ti.teis.exceptions.TeisIllegalArgumentException;
import ee.sm.ti.teis.scheduler.domain.SystemJob;
import ee.sm.ti.teis.scheduler.job.definition.JobDefinitionEntity;
import ee.sm.ti.teis.scheduler.job.definition.JobDefinitionService;
import ee.sm.ti.teis.servicerequest.RequestMetaDTO;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.test.Deployment;
import org.camunda.bpm.extension.mockito.QueryMocks;
......@@ -16,6 +18,8 @@ import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import static ee.sm.ti.teis.scheduler.processor.bpm.JobProcessInstanceContext.EXECUTE_JOB_MESSAGE_ID;
import static ee.sm.ti.teis.servicerequest.UserType.SYSTEM;
import static java.util.UUID.randomUUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.camunda.bpm.extension.mockito.CamundaMockito.autoMock;
import static org.junit.jupiter.api.Assertions.assertThrows;
......@@ -27,54 +31,62 @@ import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
@Deployment
public class JobLauncherServiceTest {
class JobLauncherServiceTest {
private static final RequestMetaDTO SYSTEM_REQUEST_META_DTO = RequestMetaDTO.builder()
.requestId(randomUUID().toString())
.userType(SYSTEM)
.build();
private static final String JOB_ID = "someJob";
@Mock
private RuntimeService camundaRuntimeService;
@Mock
private JobDefinitionService jobDefinitionService;
@Mock
private ObjectMapper objectMapper;
@InjectMocks
private JobLauncherService jobLauncherService;
private static final String JOB_ID = "someJob";
@Test
public void should_throwException_when_jobIsAlreadyRunning() {
void should_throwException_when_jobIsAlreadyRunning() {
QueryMocks.mockProcessInstanceQuery(camundaRuntimeService).count(1);
assertThrows(TeisIllegalArgumentException.class, () -> jobLauncherService.launchJob(JOB_ID));
assertThrows(TeisIllegalArgumentException.class, () -> jobLauncherService.launchJob(JOB_ID, SYSTEM_REQUEST_META_DTO));
}
@Test
public void should_runJob_whenNoJobsRunning() {
void should_runJob_whenNoJobsRunning() {
autoMock("executeSystemJobs.bpmn");
QueryMocks.mockProcessInstanceQuery(camundaRuntimeService).count(0);
when(jobDefinitionService.getJob(JOB_ID)).thenReturn(getJobDefinitionStub(JOB_ID));
SystemJob systemJob = jobLauncherService.launchJob(JOB_ID);
SystemJob systemJob = jobLauncherService.launchJob(JOB_ID, SYSTEM_REQUEST_META_DTO);
verify(camundaRuntimeService, times(1)).startProcessInstanceByMessage(eq(EXECUTE_JOB_MESSAGE_ID),
eq(JOB_ID + "::" + systemJob.getExecutionId().toString()), anyMap());
}
@Test
public void should_returnTrue_when_anyJobIsAlreadyRunning() {
void should_returnTrue_when_anyJobIsAlreadyRunning() {
QueryMocks.mockProcessInstanceQuery(camundaRuntimeService).count(1);
assertThat(jobLauncherService.isAnyProcessRunning(JOB_ID)).isTrue();
}
@Test
public void should_returnFalse_when_noJobsRunning() {
void should_returnFalse_when_noJobsRunning() {
QueryMocks.mockProcessInstanceQuery(camundaRuntimeService).count(0);
assertThat(jobLauncherService.isAnyProcessRunning(JOB_ID)).isFalse();
}
@Test
public void should_returnQuietly_whenJobIsDisabled() {
void should_returnQuietly_whenJobIsDisabled() {
QueryMocks.mockProcessInstanceQuery(camundaRuntimeService).count(0);
JobDefinitionEntity jobDefinitionEntity = getJobDefinitionStub(JOB_ID);
jobDefinitionEntity.setDisabled(true);
when(jobDefinitionService.getJob(JOB_ID)).thenReturn(jobDefinitionEntity);
SystemJob systemJob = jobLauncherService.launchJob(JOB_ID);
SystemJob systemJob = jobLauncherService.launchJob(JOB_ID, SYSTEM_REQUEST_META_DTO);
verify(camundaRuntimeService, times(0)).startProcessInstanceByMessage(eq(EXECUTE_JOB_MESSAGE_ID),
eq(JOB_ID + "::" + systemJob.getExecutionId().toString()), anyMap());
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment