FINERACT-1744 add idempotency key to command_source table
This commit is contained in:
committed by
Arnold Gálovics
parent
dae12cdd46
commit
f3aeef2f45
+15
-3
@@ -107,9 +107,13 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
@Column(name = "job_name")
|
||||
private String jobName;
|
||||
|
||||
public static CommandSource fullEntryFrom(final CommandWrapper wrapper, final JsonCommand command, final AppUser maker) {
|
||||
@Column(name = "idempotency_key", length = 50)
|
||||
private String idempotencyKey;
|
||||
|
||||
public static CommandSource fullEntryFrom(final CommandWrapper wrapper, final JsonCommand command, final AppUser maker,
|
||||
String idempotencyKey) {
|
||||
return new CommandSource(wrapper.actionName(), wrapper.entityName(), wrapper.getHref(), command.entityId(), command.subentityId(),
|
||||
command.json(), maker);
|
||||
command.json(), maker, idempotencyKey);
|
||||
}
|
||||
|
||||
protected CommandSource() {
|
||||
@@ -117,7 +121,7 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
}
|
||||
|
||||
private CommandSource(final String actionName, final String entityName, final String href, final Long resourceId,
|
||||
final Long subresourceId, final String commandSerializedAsJson, final AppUser maker) {
|
||||
final Long subresourceId, final String commandSerializedAsJson, final AppUser maker, final String idempotencyKey) {
|
||||
this.actionName = actionName;
|
||||
this.entityName = entityName;
|
||||
this.resourceGetUrl = href;
|
||||
@@ -127,6 +131,7 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
this.maker = maker;
|
||||
this.madeOnDate = DateUtils.getOffsetDateTimeOfTenant();
|
||||
this.processingResult = CommandProcessingResultType.PROCESSED.getValue();
|
||||
this.idempotencyKey = idempotencyKey;
|
||||
}
|
||||
|
||||
public Long getCreditBureauId() {
|
||||
@@ -286,4 +291,11 @@ public class CommandSource extends AbstractPersistableCustom {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getIdempotencyKey() {
|
||||
return idempotencyKey;
|
||||
}
|
||||
|
||||
public void setIdempotencyKey(String idempotencyKey) {
|
||||
this.idempotencyKey = idempotencyKey;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-4
@@ -42,6 +42,8 @@ public class CommandWrapper {
|
||||
private final Long organisationCreditBureauId;
|
||||
private final String jobName;
|
||||
|
||||
private final String idempotencyKey;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Long templateId;
|
||||
|
||||
@@ -57,9 +59,9 @@ public class CommandWrapper {
|
||||
public static CommandWrapper fromExistingCommand(final Long commandId, final String actionName, final String entityName,
|
||||
final Long resourceId, final Long subresourceId, final String resourceGetUrl, final Long productId, final Long officeId,
|
||||
final Long groupId, final Long clientId, final Long loanId, final Long savingsId, final String transactionId,
|
||||
final Long creditBureauId, final Long organisationCreditBureauId) {
|
||||
final Long creditBureauId, final Long organisationCreditBureauId, final String idempotencyKey) {
|
||||
return new CommandWrapper(commandId, actionName, entityName, resourceId, subresourceId, resourceGetUrl, productId, officeId,
|
||||
groupId, clientId, loanId, savingsId, transactionId, creditBureauId, organisationCreditBureauId);
|
||||
groupId, clientId, loanId, savingsId, transactionId, creditBureauId, organisationCreditBureauId, idempotencyKey);
|
||||
}
|
||||
|
||||
private CommandWrapper(final Long commandId, final String actionName, final String entityName, final Long resourceId,
|
||||
@@ -82,12 +84,13 @@ public class CommandWrapper {
|
||||
this.creditBureauId = null;
|
||||
this.organisationCreditBureauId = null;
|
||||
this.jobName = null;
|
||||
this.idempotencyKey = null;
|
||||
}
|
||||
|
||||
public CommandWrapper(final Long officeId, final Long groupId, final Long clientId, final Long loanId, final Long savingsId,
|
||||
final String actionName, final String entityName, final Long entityId, final Long subentityId, final String href,
|
||||
final String json, final String transactionId, final Long productId, final Long templateId, final Long creditBureauId,
|
||||
final Long organisationCreditBureauId, final String jobName) {
|
||||
final Long organisationCreditBureauId, final String jobName, final String idempotencyKey) {
|
||||
|
||||
this.commandId = null;
|
||||
this.officeId = officeId;
|
||||
@@ -108,12 +111,13 @@ public class CommandWrapper {
|
||||
this.creditBureauId = creditBureauId;
|
||||
this.organisationCreditBureauId = organisationCreditBureauId;
|
||||
this.jobName = jobName;
|
||||
this.idempotencyKey = idempotencyKey;
|
||||
}
|
||||
|
||||
private CommandWrapper(final Long commandId, final String actionName, final String entityName, final Long resourceId,
|
||||
final Long subresourceId, final String resourceGetUrl, final Long productId, final Long officeId, final Long groupId,
|
||||
final Long clientId, final Long loanId, final Long savingsId, final String transactionId, final Long creditBureauId,
|
||||
final Long organisationCreditBureauId) {
|
||||
final Long organisationCreditBureauId, final String idempotencyKey) {
|
||||
|
||||
this.commandId = commandId;
|
||||
this.officeId = officeId;
|
||||
@@ -133,6 +137,7 @@ public class CommandWrapper {
|
||||
this.creditBureauId = creditBureauId;
|
||||
this.organisationCreditBureauId = organisationCreditBureauId;
|
||||
this.jobName = null;
|
||||
this.idempotencyKey = idempotencyKey;
|
||||
}
|
||||
|
||||
public Long getCreditBureauId() {
|
||||
@@ -143,6 +148,10 @@ public class CommandWrapper {
|
||||
return this.organisationCreditBureauId;
|
||||
}
|
||||
|
||||
public String getIdempotencyKey() {
|
||||
return idempotencyKey;
|
||||
}
|
||||
|
||||
public String getHref() {
|
||||
return this.href;
|
||||
}
|
||||
|
||||
+8
-1
@@ -45,11 +45,18 @@ public class CommandWrapperBuilder {
|
||||
private Long creditBureauId;
|
||||
private Long organisationCreditBureauId;
|
||||
private String jobName;
|
||||
private String idempotencyKey;
|
||||
|
||||
public CommandWrapper build() {
|
||||
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName, this.entityName,
|
||||
this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, this.templateId,
|
||||
this.creditBureauId, this.organisationCreditBureauId, this.jobName);
|
||||
this.creditBureauId, this.organisationCreditBureauId, this.jobName, this.idempotencyKey);
|
||||
}
|
||||
|
||||
public CommandWrapper build(String idempotencyKey) {
|
||||
return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName, this.entityName,
|
||||
this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, this.templateId,
|
||||
this.creditBureauId, this.organisationCreditBureauId, this.jobName, idempotencyKey);
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateCreditBureau() {
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.service;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class IdempotencyKeyGenerator {
|
||||
|
||||
public String create() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -130,7 +130,7 @@ public class PortfolioCommandSourceWritePlatformServiceImpl implements Portfolio
|
||||
commandSourceInput.getResourceGetUrl(), commandSourceInput.getProductId(), commandSourceInput.getOfficeId(),
|
||||
commandSourceInput.getGroupId(), commandSourceInput.getClientId(), commandSourceInput.getLoanId(),
|
||||
commandSourceInput.getSavingsId(), commandSourceInput.getTransactionId(), commandSourceInput.getCreditBureauId(),
|
||||
commandSourceInput.getOrganisationCreditBureauId());
|
||||
commandSourceInput.getOrganisationCreditBureauId(), commandSourceInput.getIdempotencyKey());
|
||||
final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSourceInput.json());
|
||||
final JsonCommand command = JsonCommand.fromExistingCommand(makerCheckerId, commandSourceInput.json(), parsedCommand,
|
||||
this.fromApiJsonHelper, commandSourceInput.getEntityName(), commandSourceInput.resourceId(),
|
||||
|
||||
+7
-1
@@ -63,6 +63,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final CommandHandlerProvider commandHandlerProvider;
|
||||
|
||||
private final IdempotencyKeyGenerator idempotencyKeyGenerator;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult executeCommand(final CommandWrapper wrapper, final JsonCommand command,
|
||||
@@ -88,7 +90,8 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
.orElseThrow(() -> new CommandNotFoundException(command.commandId()));
|
||||
commandSourceResult.markAsChecked(maker);
|
||||
} else {
|
||||
commandSourceResult = CommandSource.fullEntryFrom(wrapper, command, maker);
|
||||
commandSourceResult = CommandSource.fullEntryFrom(wrapper, command, maker,
|
||||
wrapper.getIdempotencyKey() == null ? idempotencyKeyGenerator.create() : wrapper.getIdempotencyKey());
|
||||
}
|
||||
commandSourceResult.updateResourceId(result.getResourceId());
|
||||
commandSourceResult.updateForAudit(result.getOfficeId(), result.getGroupId(), result.getClientId(), result.getLoanId(),
|
||||
@@ -134,6 +137,9 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
public CommandProcessingResult logCommand(CommandSource commandSourceResult) {
|
||||
|
||||
commandSourceResult.markAsAwaitingApproval();
|
||||
if (commandSourceResult.getIdempotencyKey() == null) {
|
||||
commandSourceResult.setIdempotencyKey(idempotencyKeyGenerator.create());
|
||||
}
|
||||
commandSourceResult = commandSourceRepository.saveAndFlush(commandSourceResult);
|
||||
|
||||
return new CommandProcessingResultBuilder().withCommandId(commandSourceResult.getId())
|
||||
|
||||
+6
-2
@@ -27,6 +27,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.IdempotencyKeyGenerator;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.bulkimport.constants.CenterConstants;
|
||||
import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
|
||||
@@ -62,10 +63,13 @@ public class CenterImportHandler implements ImportHandler {
|
||||
private Workbook workbook;
|
||||
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final IdempotencyKeyGenerator idempotencyKeyGenerator;
|
||||
|
||||
@Autowired
|
||||
public CenterImportHandler(final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
|
||||
public CenterImportHandler(final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
IdempotencyKeyGenerator idempotencyKeyGenerator) {
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.idempotencyKeyGenerator = idempotencyKeyGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -262,7 +266,7 @@ public class CenterImportHandler implements ImportHandler {
|
||||
String payload = gsonBuilder.create().toJson(calendarData);
|
||||
CommandWrapper commandWrapper = new CommandWrapper(result.getOfficeId(), result.getGroupId(), result.getClientId(),
|
||||
result.getLoanId(), result.getSavingsId(), null, null, null, null, null, payload, result.getTransactionId(),
|
||||
result.getProductId(), null, null, null, null);
|
||||
result.getProductId(), null, null, null, null, idempotencyKeyGenerator.create());
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
|
||||
.createCalendar(commandWrapper, TemplatePopulateImportConstants.CENTER_ENTITY_TYPE, result.getGroupId()) //
|
||||
.withJson(payload) //
|
||||
|
||||
+6
-2
@@ -27,6 +27,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.IdempotencyKeyGenerator;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.bulkimport.constants.GroupConstants;
|
||||
import org.apache.fineract.infrastructure.bulkimport.constants.TemplatePopulateImportConstants;
|
||||
@@ -62,10 +63,13 @@ public class GroupImportHandler implements ImportHandler {
|
||||
private List<String> statuses;
|
||||
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final IdempotencyKeyGenerator idempotencyKeyGenerator;
|
||||
|
||||
@Autowired
|
||||
public GroupImportHandler(final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
|
||||
public GroupImportHandler(final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
|
||||
IdempotencyKeyGenerator idempotencyKeyGenerator) {
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.idempotencyKeyGenerator = idempotencyKeyGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,7 +245,7 @@ public class GroupImportHandler implements ImportHandler {
|
||||
String payload = gsonBuilder.create().toJson(calendarData);
|
||||
CommandWrapper commandWrapper = new CommandWrapper(result.getOfficeId(), result.getGroupId(), result.getClientId(),
|
||||
result.getLoanId(), result.getSavingsId(), null, null, null, null, null, payload, result.getTransactionId(),
|
||||
result.getProductId(), null, null, null, null);
|
||||
result.getProductId(), null, null, null, null, idempotencyKeyGenerator.create());
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
|
||||
.createCalendar(commandWrapper, TemplatePopulateImportConstants.CENTER_ENTITY_TYPE, result.getGroupId()) //
|
||||
.withJson(payload) //
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public class InteropWrapperBuilder {
|
||||
|
||||
public CommandWrapper build() {
|
||||
return new CommandWrapper(null, null, null, null, null, actionName, entityName, null, null, href, json, null, null, null, null,
|
||||
null, null);
|
||||
null, null, null);
|
||||
}
|
||||
|
||||
public InteropWrapperBuilder withJson(final String json) {
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
<property name="current_date" value="CURDATE()" context="mysql"/>
|
||||
<property name="current_date" value="CURRENT_DATE" context="postgresql"/>
|
||||
<property name="current_datetime" value="NOW()"/>
|
||||
<property name="uuid" value="uuid()" context="mysql"/>
|
||||
<property name="uuid" value="uuid_generate_v4()" context="postgresql"/>
|
||||
<include file="tenant-store/initial-switch-changelog-tenant-store.xml" relativeToChangelogFile="true" context="tenant_store_db AND initial_switch"/>
|
||||
<include file="tenant-store/changelog-tenant-store.xml" relativeToChangelogFile="true" context="tenant_store_db AND !initial_switch"/>
|
||||
<include file="tenant/initial-switch-changelog-tenant.xml" relativeToChangelogFile="true" context="tenant_db AND initial_switch"/>
|
||||
|
||||
@@ -80,4 +80,5 @@
|
||||
<include file="parts/0058_add_execute_inline_cob_permission.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0059_add_spring_batch_loan_id_list_table.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0060_add_job_name_to_command_source.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0061_add_idempotency_key_to_command_source.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.1.xsd">
|
||||
<changeSet author="fineract" id="1" context="postgresql">
|
||||
<sql>
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="fineract" id="2">
|
||||
<addColumn tableName="m_portfolio_command_source">
|
||||
<column defaultValueComputed="NULL" name="idempotency_key" type="VARCHAR(50)"/>
|
||||
</addColumn>
|
||||
<update tableName="m_portfolio_command_source">
|
||||
<column name="idempotency_key" valueComputed="${uuid}" />
|
||||
<where>idempotency_key is null</where>
|
||||
</update>
|
||||
<addUniqueConstraint columnNames="action_name, entity_name, idempotency_key" constraintName="UNIQUE_PORTFOLIO_COMMAND_SOURCE"
|
||||
tableName="m_portfolio_command_source"/>
|
||||
<createIndex indexName="portfolio_command_source_composite_index" tableName="m_portfolio_command_source">
|
||||
<column name="action_name"/>
|
||||
<column name="entity_name"/>
|
||||
<column name="idempotency_key"/>
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="fineract" id="3" context="postgresql">
|
||||
<addNotNullConstraint columnName="idempotency_key"
|
||||
constraintName="mpcs_idempotency_key_nn"
|
||||
tableName="m_portfolio_command_source"/>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="fineract" id="4" context="mysql">
|
||||
<sql>
|
||||
ALTER TABLE m_portfolio_command_source MODIFY idempotency_key VARCHAR(50) not NULL
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
Reference in New Issue
Block a user