FINERACT-1744
- [x] Purge Processed Commands Jobs - [x] Refactor CommandProcessingResultType to CommandProcessingStatus
This commit is contained in:
committed by
Arnold Gálovics
parent
0c63bf2f27
commit
8c7e417c5d
+7
@@ -18,11 +18,18 @@
|
||||
*/
|
||||
package org.apache.fineract.commands.domain;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
public interface CommandSourceRepository extends JpaRepository<CommandSource, Long>, JpaSpecificationExecutor<CommandSource> {
|
||||
|
||||
CommandSource findByActionNameAndEntityNameAndIdempotencyKey(String actionName, String entityName, String idempotencyKey);
|
||||
|
||||
@Modifying(flushAutomatically = true)
|
||||
@Query("delete from CommandSource c where c.status = :status and c.madeOnDate is not null and c.madeOnDate <= :dateForPurgeCriteria")
|
||||
void deleteOlderEventsWithStatus(CommandProcessingResultType status, LocalDate dateForPurgeCriteria);
|
||||
|
||||
}
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.commands.jobs;
|
||||
|
||||
import org.apache.fineract.infrastructure.jobs.service.JobName;
|
||||
import org.apache.fineract.infrastructure.jobs.service.StepName;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
|
||||
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
|
||||
import org.springframework.batch.core.launch.support.RunIdIncrementer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class PurgeProcessedCommandsConfig {
|
||||
|
||||
@Autowired
|
||||
private JobBuilderFactory jobs;
|
||||
@Autowired
|
||||
private StepBuilderFactory steps;
|
||||
@Autowired
|
||||
private PurgeProcessedCommandsTasklet tasklet;
|
||||
|
||||
@Bean
|
||||
protected Step purgeProcessedCommandsStep() {
|
||||
return steps.get(StepName.PURGE_PROCESSED_COMMANDS_STEP.name()).tasklet(tasklet).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Job purgeProcessedCommandsJob() {
|
||||
return jobs.get(JobName.PURGE_PROCESSED_COMMANDS.name()).start(purgeProcessedCommandsStep()).incrementer(new RunIdIncrementer())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.commands.jobs;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.fineract.commands.domain.CommandProcessingResultType;
|
||||
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@Component
|
||||
public class PurgeProcessedCommandsTasklet implements Tasklet {
|
||||
|
||||
private final CommandSourceRepository repository;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
|
||||
try {
|
||||
Long numberOfDaysForPurgeCriteria = configurationDomainService.retrieveProcessedCommandsPurgeDaysCriteria();
|
||||
LocalDate dateForPurgeCriteria = DateUtils.getBusinessLocalDate().minusDays(numberOfDaysForPurgeCriteria);
|
||||
repository.deleteOlderEventsWithStatus(CommandProcessingResultType.PROCESSED, dateForPurgeCriteria);
|
||||
} catch (Exception e) {
|
||||
log.error("Error occurred while purging processed commands: ", e);
|
||||
}
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
|
||||
}
|
||||
+2
@@ -121,6 +121,8 @@ public interface ConfigurationDomainService {
|
||||
|
||||
Long retrieveExternalEventsPurgeDaysCriteria();
|
||||
|
||||
Long retrieveProcessedCommandsPurgeDaysCriteria();
|
||||
|
||||
Long retrieveRepaymentDueDays();
|
||||
|
||||
Long retrieveRepaymentOverdueDays();
|
||||
|
||||
+9
@@ -41,6 +41,8 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
public static final String ENABLE_BUSINESS_DATE = "enable_business_date";
|
||||
public static final String ENABLE_AUTOMATIC_COB_DATE_ADJUSTMENT = "enable_automatic_cob_date_adjustment";
|
||||
public static final String EXTERNAL_EVENTS_PURGE_DAYS = "purge-external-events-older-than-days";
|
||||
|
||||
public static final String PROCESSED_COMMANDS_PURGE_DAYS = "purge-processed-commands-older-than-days";
|
||||
private static final String DAYS_BEFORE_REPAYMENT_IS_DUE = "days-before-repayment-is-due";
|
||||
private static final String DAYS_AFTER_REPAYMENT_IS_OVERDUE = "days-after-repayment-is-overdue";
|
||||
private static final String ENABLE_EXTERNAL_ID_AUTO_GENERATION = "enable-auto-generated-external-id";
|
||||
@@ -463,6 +465,13 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long retrieveProcessedCommandsPurgeDaysCriteria() {
|
||||
final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(PROCESSED_COMMANDS_PURGE_DAYS);
|
||||
return property.getValue();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long retrieveRepaymentDueDays() {
|
||||
final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(DAYS_BEFORE_REPAYMENT_IS_DUE);
|
||||
|
||||
+2
-1
@@ -55,7 +55,8 @@ public enum JobName {
|
||||
LOAN_COB("Loan COB"), //
|
||||
LOAN_DELINQUENCY_CLASSIFICATION("Loan Delinquency Classification"), //
|
||||
SEND_ASYNCHRONOUS_EVENTS("Send Asynchronous Events"), //
|
||||
PURGE_EXTERNAL_EVENTS("Purge External Events");
|
||||
PURGE_EXTERNAL_EVENTS("Purge External Events"), //
|
||||
PURGE_PROCESSED_COMMANDS("Purge Processed Commands");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.infrastructure.jobs.service;
|
||||
|
||||
public enum StepName {
|
||||
PURGE_PROCESSED_COMMANDS_STEP;
|
||||
}
|
||||
@@ -94,4 +94,5 @@
|
||||
<include file="parts/0072_add_result_and status_to_command_source.xml" relativeToChangelogFile="true" />
|
||||
<include file="parts/0073_add_result_status_code_to_command_source.xml" relativeToChangelogFile="true" />
|
||||
<include file="parts/0074_add_last_cob_business_date_column_to_loan.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0075_add_processed_commands_purge_job.xml" relativeToChangelogFile="true" />
|
||||
</databaseChangeLog>
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
|
||||
<changeSet author="fineract" id="1" context="postgresql">
|
||||
<sql>
|
||||
SELECT SETVAL('c_configuration_id_seq', COALESCE(MAX(id), 0)+1, false ) FROM c_configuration;
|
||||
</sql>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="2">
|
||||
<insert tableName="c_configuration">
|
||||
<column name="name" value="purge-processed-commands-older-than-days"/>
|
||||
<column name="value" valueNumeric="30"/>
|
||||
<column name="date_value"/>
|
||||
<column name="string_value"/>
|
||||
<column name="enabled" valueBoolean="false"/>
|
||||
<column name="is_trap_door" valueBoolean="false"/>
|
||||
<column name="description" value="Number of days criteria to purge old processed commands"/>
|
||||
</insert>
|
||||
<insert tableName="job">
|
||||
<column name="name" value="Purge Processed Commands"/>
|
||||
<column name="display_name" value="Purge Processed Commands"/>
|
||||
<column name="cron_expression" value="0 0 1 * * ?"/>
|
||||
<column name="create_time" valueDate="${current_datetime}"/>
|
||||
<column name="task_priority" valueNumeric="5"/>
|
||||
<column name="group_name"/>
|
||||
<column name="previous_run_start_time"/>
|
||||
<column name="job_key" value="Purge Processed Commands _ DEFAULT"/>
|
||||
<column name="initializing_errorlog"/>
|
||||
<column name="is_active" valueBoolean="false"/>
|
||||
<column name="currently_running" valueBoolean="false"/>
|
||||
<column name="updates_allowed" valueBoolean="true"/>
|
||||
<column name="scheduler_group" valueNumeric="0"/>
|
||||
<column name="is_misfired" valueBoolean="false"/>
|
||||
<column name="node_id" valueNumeric="1"/>
|
||||
<column name="is_mismatched_job" valueBoolean="true"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.commands.jobs;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.commands.domain.CommandSourceRepository;
|
||||
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
|
||||
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
|
||||
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
import org.springframework.batch.core.scope.context.ChunkContext;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class PurgeProcessedCommandsTaskletTest {
|
||||
|
||||
@Mock
|
||||
private CommandSourceRepository repository;
|
||||
@Mock
|
||||
private ConfigurationDomainService configurationDomainService;
|
||||
@Mock
|
||||
private StepContribution stepContribution;
|
||||
@Mock
|
||||
private ChunkContext chunkContext;
|
||||
private RepeatStatus resultStatus;
|
||||
private PurgeProcessedCommandsTasklet underTest;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
|
||||
ThreadLocalContextUtil
|
||||
.setBusinessDates(new HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.now(ZoneId.systemDefault()))));
|
||||
underTest = new PurgeProcessedCommandsTasklet(repository, configurationDomainService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEventsForPurgeWhenTaskExecutionThenEventsPurgeForDaysCriteria() {
|
||||
// given
|
||||
ArgumentCaptor<LocalDate> dateCriteriaCaptor = ArgumentCaptor.forClass(LocalDate.class);
|
||||
when(configurationDomainService.retrieveProcessedCommandsPurgeDaysCriteria()).thenReturn(2L);
|
||||
// when
|
||||
resultStatus = underTest.execute(stepContribution, chunkContext);
|
||||
// then
|
||||
verify(repository, times(1)).deleteOlderEventsWithStatus(Mockito.any(), Mockito.any());
|
||||
verify(repository).deleteOlderEventsWithStatus(Mockito.any(), dateCriteriaCaptor.capture());
|
||||
LocalDate expectedDateForPurgeCriteriaTest = DateUtils.getBusinessLocalDate().minusDays(2);
|
||||
LocalDate actualDateForPurgeCriteria = dateCriteriaCaptor.getValue();
|
||||
assertEquals(expectedDateForPurgeCriteriaTest, actualDateForPurgeCriteria);
|
||||
assertEquals(RepeatStatus.FINISHED, resultStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEventsForPurgeWhenExceptionOccursThenJobExecutionFinishesSuccessfully() {
|
||||
// given
|
||||
when(configurationDomainService.retrieveProcessedCommandsPurgeDaysCriteria()).thenReturn(2L);
|
||||
doThrow(new RuntimeException("Test Exception")).when(repository).deleteOlderEventsWithStatus(Mockito.any(), Mockito.any());
|
||||
// when
|
||||
resultStatus = underTest.execute(stepContribution, chunkContext);
|
||||
// then
|
||||
assertEquals(RepeatStatus.FINISHED, resultStatus);
|
||||
}
|
||||
|
||||
}
|
||||
+10
-3
@@ -98,9 +98,9 @@ public class GlobalConfigurationHelper {
|
||||
ArrayList<HashMap> expectedGlobalConfigurations = getAllDefaultGlobalConfigurations();
|
||||
ArrayList<HashMap> actualGlobalConfigurations = getAllGlobalConfigurations(requestSpec, responseSpec);
|
||||
|
||||
// There are currently 45 global configurations.
|
||||
Assertions.assertEquals(45, expectedGlobalConfigurations.size());
|
||||
Assertions.assertEquals(45, actualGlobalConfigurations.size());
|
||||
// There are currently 46 global configurations.
|
||||
Assertions.assertEquals(46, expectedGlobalConfigurations.size());
|
||||
Assertions.assertEquals(46, actualGlobalConfigurations.size());
|
||||
|
||||
for (int i = 0; i < expectedGlobalConfigurations.size(); i++) {
|
||||
|
||||
@@ -496,6 +496,13 @@ public class GlobalConfigurationHelper {
|
||||
isAutomaticExternalIdGenerationEnabled.put("trapDoor", false);
|
||||
defaults.add(isAutomaticExternalIdGenerationEnabled);
|
||||
|
||||
HashMap<String, Object> purgeProcessCommandDaysDefault = new HashMap<>();
|
||||
purgeProcessCommandDaysDefault.put("id", 51);
|
||||
purgeProcessCommandDaysDefault.put("name", "purge-processed-commands-older-than-days");
|
||||
purgeProcessCommandDaysDefault.put("value", 0);
|
||||
purgeProcessCommandDaysDefault.put("enabled", false);
|
||||
purgeProcessCommandDaysDefault.put("trapDoor", false);
|
||||
defaults.add(purgeProcessCommandDaysDefault);
|
||||
return defaults;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user