modify calculation limit total value (#23)

* modify calculation limit total value

* review

* review(2)

* review (3)

* review (4)
This commit is contained in:
Gregory 2024-10-16 16:48:56 +03:00 committed by GitHub
parent db4d2ae383
commit b201b272a9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 230 additions and 227 deletions

View File

@ -1,35 +0,0 @@
package com.empayre.liminator.converter;
import com.empayre.liminator.model.LimitValue;
import dev.vality.liminator.LimitResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Component
public class CurrentLimitValuesToLimitResponseConverter implements Converter<List<LimitValue>, List<LimitResponse>> {
@Override
public List<LimitResponse> convert(List<LimitValue> values) {
if (values == null) {
log.info("Received LimitValues array is empty");
return new ArrayList<>();
}
return values.stream()
.map(limitValue -> new LimitResponse(
limitValue.getLimitName(),
limitValue.getCommitValue(),
getTotalValue(limitValue))
.setLimitId(limitValue.getLimitId())
)
.toList();
}
private static long getTotalValue(LimitValue limitValue) {
return limitValue.getHoldValue() + limitValue.getCommitValue() - limitValue.getRollbackValue();
}
}

View File

@ -0,0 +1,41 @@
package com.empayre.liminator.converter;
import com.empayre.liminator.model.LimitValue;
import dev.vality.liminator.LimitResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import static java.util.stream.Collectors.groupingBy;
@Slf4j
@Component
public class LimitValuesByLimitNameToLimitResponseConverter
implements Converter<Map.Entry<String, List<LimitValue>>, LimitResponse> {
@Override
public LimitResponse convert(Map.Entry<String, List<LimitValue>> source) {
LimitResponse limitResponse = new LimitResponse();
limitResponse.setLimitName(source.getKey());
limitResponse.setLimitId(source.getValue().get(0).getLimitId());
long commitValue = 0L;
long totalValue = 0L;
for (LimitValue limitValue : source.getValue()) {
switch (limitValue.getState()) {
case HOLD -> totalValue = totalValue + limitValue.getOperationValue();
case COMMIT -> {
commitValue = commitValue + limitValue.getOperationValue();
totalValue = totalValue - limitValue.getOperationValue();
}
case ROLLBACK -> totalValue = totalValue - limitValue.getOperationValue();
default -> throw new IllegalStateException("Unexpected value: " + limitValue.getState());
}
}
limitResponse.setCommitValue(commitValue);
limitResponse.setTotalValue(totalValue);
return limitResponse;
}
}

View File

@ -0,0 +1,36 @@
package com.empayre.liminator.converter;
import com.empayre.liminator.model.LimitValue;
import dev.vality.liminator.LimitResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static java.util.stream.Collectors.groupingBy;
@Slf4j
@Component
@RequiredArgsConstructor
public class LimitValuesToLimitResponsesConverter implements Converter<List<LimitValue>, List<LimitResponse>> {
private final Converter<Map.Entry<String, List<LimitValue>>, LimitResponse> limitResponseConverter;
@Override
public List<LimitResponse> convert(List<LimitValue> values) {
if (CollectionUtils.isEmpty(values)) {
log.info("Received LimitValues array is empty");
return new ArrayList<>();
}
Map<String, List<LimitValue>> valuesPerLimitName = values.stream()
.collect(groupingBy(LimitValue::getLimitName));
return valuesPerLimitName.entrySet().stream()
.map(limitResponseConverter::convert)
.toList();
}
}

View File

@ -11,9 +11,9 @@ public interface OperationStateHistoryDao extends CommonDao<OperationStateHistor
int[] saveBatch(List<OperationStateHistory> historyList); int[] saveBatch(List<OperationStateHistory> historyList);
List<LimitValue> getCurrentLimitValue(List<String> limitNames); List<LimitValue> getLimitHistory(List<String> limitNames);
List<LimitValue> getCurrentLimitValue(List<String> limitNames, String operationId); List<LimitValue> getLimitHistory(List<String> limitNames, String operationId);
List<OperationStateHistory> get(String operationId, Collection<Long> limitIds, List<OperationState> states); List<OperationStateHistory> get(String operationId, Collection<Long> limitIds, List<OperationState> states);
} }

View File

@ -6,23 +6,23 @@ import com.empayre.liminator.domain.tables.pojos.OperationStateHistory;
import com.empayre.liminator.model.LimitValue; import com.empayre.liminator.model.LimitValue;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.jooq.DSLContext; import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.RecordMapper;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import static com.empayre.liminator.domain.Tables.LIMIT_DATA;
import static com.empayre.liminator.domain.Tables.OPERATION_STATE_HISTORY; import static com.empayre.liminator.domain.Tables.OPERATION_STATE_HISTORY;
import static org.jooq.impl.DSL.raw; import static org.jooq.impl.DSL.select;
import static org.jooq.impl.DSL.val;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
public class OperationStateHistoryDaoImpl implements OperationStateHistoryDao { public class OperationStateHistoryDaoImpl implements OperationStateHistoryDao {
private static final String DELIMITER = " ,";
private final DSLContext dslContext; private final DSLContext dslContext;
private final RecordMapper<Record, LimitValue> recordMapper;
@Override @Override
public Long save(OperationStateHistory history) { public Long save(OperationStateHistory history) {
@ -45,88 +45,32 @@ public class OperationStateHistoryDaoImpl implements OperationStateHistoryDao {
} }
@Override @Override
public List<LimitValue> getCurrentLimitValue(List<String> limitNames) { public List<LimitValue> getLimitHistory(List<String> limitNames) {
String sql = """
with hold_data as (
select ld.id, ld.name, ld.limit_id, coalesce(sum(ops.operation_value), 0) as hold_value
from lim.limit_data as ld
left join lim.operation_state_history as ops
on ops.limit_name = ld.name
and ops.state = 'HOLD'
where ld.name in ({0})
group by ld.id, ld.name
), commit_data as (
select ld.id, ld.name, ld.limit_id, coalesce(sum(ops.operation_value), 0) as commit_value
from lim.limit_data as ld
left join lim.operation_state_history as ops
on ops.limit_name = ld.name
and ops.state = 'COMMIT'
where ld.name in ({0})
group by ld.id, ld.name
), rollback_data as (
select ld.id, ld.name, ld.limit_id, coalesce(sum(ops.operation_value), 0) as rollback_value
from lim.limit_data as ld
left join lim.operation_state_history as ops
on ops.limit_name = ld.name
and ops.state = 'ROLLBACK'
where ld.name in ({0})
group by ld.id, ld.name
)
select cd.limit_id, cd.name as limit_name, cd.commit_value, hd.hold_value, rd.rollback_value
from commit_data as cd
join hold_data as hd on cd.id = hd.id
join rollback_data as rd on cd.id = rd.id;
""";
return dslContext return dslContext
.resultQuery(sql, raw(arrayToString(limitNames))) .select()
.fetchInto(LimitValue.class); .from(OPERATION_STATE_HISTORY.join(LIMIT_DATA)
.on(OPERATION_STATE_HISTORY.LIMIT_DATA_ID.eq(LIMIT_DATA.ID))
.and(LIMIT_DATA.NAME.in(limitNames)))
.fetch()
.map(recordMapper);
} }
@Override @Override
public List<LimitValue> getCurrentLimitValue(List<String> limitNames, String operationId) { public List<LimitValue> getLimitHistory(List<String> limitNames, String operationId) {
String sql = """
with operation_timestamp as (
select created_at
from lim.operation_state_history
where operation_id = {0}
), hold_data as (
select ld.id, ld.name, ld.limit_id, coalesce(sum(ops.operation_value), 0) as hold_value
from lim.limit_data as ld
left join lim.operation_state_history as ops
on ops.limit_name = ld.name
and ops.created_at <= (select created_at from operation_timestamp limit 1)
and ops.state = 'HOLD'
where ld.name in ({1})
group by ld.id, ld.name
), commit_data as (
select ld.id, ld.name, ld.limit_id, coalesce(sum(ops.operation_value), 0) as commit_value
from lim.limit_data as ld
left join lim.operation_state_history as ops
on ops.limit_name = ld.name
and ops.created_at <= (select created_at from operation_timestamp limit 1)
and ops.state = 'COMMIT'
where ld.name in ({1})
group by ld.id, ld.name
), rollback_data as (
select ld.id, ld.name, ld.limit_id, coalesce(sum(ops.operation_value), 0) as rollback_value
from lim.limit_data as ld
left join lim.operation_state_history as ops
on ops.limit_name = ld.name
and ops.created_at <= (select created_at from operation_timestamp limit 1)
and ops.state = 'ROLLBACK'
where ld.name in ({1})
group by ld.id, ld.name
)
select cd.limit_id, cd.name as limit_name, cd.commit_value, hd.hold_value, rd.rollback_value
from commit_data as cd
join hold_data as hd on cd.id = hd.id
join rollback_data as rd on cd.id = rd.id;
""";
return dslContext return dslContext
.resultQuery(sql, val(operationId), raw(arrayToString(limitNames))) .select()
.fetchInto(LimitValue.class); .from(OPERATION_STATE_HISTORY.join(LIMIT_DATA)
.on(OPERATION_STATE_HISTORY.LIMIT_DATA_ID.eq(LIMIT_DATA.ID))
.and(LIMIT_DATA.NAME.in(limitNames)))
.where(OPERATION_STATE_HISTORY.CREATED_AT.le(
select(OPERATION_STATE_HISTORY.CREATED_AT)
.from(OPERATION_STATE_HISTORY)
.where(OPERATION_STATE_HISTORY.OPERATION_ID.eq(operationId))
.limit(1)
)
)
.fetch()
.map(recordMapper);
} }
@Override @Override
@ -134,16 +78,11 @@ public class OperationStateHistoryDaoImpl implements OperationStateHistoryDao {
Collection<Long> limitIds, Collection<Long> limitIds,
List<OperationState> states) { List<OperationState> states) {
return dslContext return dslContext
.selectFrom(OPERATION_STATE_HISTORY) .select()
.from(OPERATION_STATE_HISTORY)
.where(OPERATION_STATE_HISTORY.OPERATION_ID.eq(operationId)) .where(OPERATION_STATE_HISTORY.OPERATION_ID.eq(operationId))
.and(OPERATION_STATE_HISTORY.LIMIT_DATA_ID.in(limitIds)) .and(OPERATION_STATE_HISTORY.LIMIT_DATA_ID.in(limitIds))
.and(OPERATION_STATE_HISTORY.STATE.in(states)) .and(OPERATION_STATE_HISTORY.STATE.in(states))
.fetchInto(OperationStateHistory.class); .fetchInto(OperationStateHistory.class);
} }
private static String arrayToString(List<String> strings) {
return strings.stream()
.map(limit -> "'%s'".formatted(limit))
.collect(Collectors.joining(DELIMITER));
}
} }

View File

@ -0,0 +1,23 @@
package com.empayre.liminator.dao.mapper;
import com.empayre.liminator.domain.enums.OperationState;
import com.empayre.liminator.model.LimitValue;
import org.jooq.Record;
import org.jooq.RecordMapper;
import org.springframework.stereotype.Component;
import static com.empayre.liminator.domain.Tables.OPERATION_STATE_HISTORY;
import static com.empayre.liminator.domain.Tables.LIMIT_DATA;
@Component
public class LimitValueMapper implements RecordMapper<Record, LimitValue> {
@Override
public LimitValue map(Record opsDataRecord) {
String limitId = opsDataRecord.get(LIMIT_DATA.LIMIT_ID);
String limitName = opsDataRecord.get(OPERATION_STATE_HISTORY.LIMIT_NAME);
Long operationValue = opsDataRecord.get(OPERATION_STATE_HISTORY.OPERATION_VALUE);
OperationState state = OperationState.valueOf(opsDataRecord.get("state", String.class));
return new LimitValue(limitId, limitName, state, operationValue);
}
}

View File

@ -5,19 +5,20 @@ import com.empayre.liminator.domain.tables.pojos.LimitData;
import com.empayre.liminator.handler.HoldOperationHandler; import com.empayre.liminator.handler.HoldOperationHandler;
import com.empayre.liminator.service.LimitDataService; import com.empayre.liminator.service.LimitDataService;
import com.empayre.liminator.service.LimitOperationsHistoryService; import com.empayre.liminator.service.LimitOperationsHistoryService;
import dev.vality.liminator.DuplicateOperation;
import dev.vality.liminator.LimitChange; import dev.vality.liminator.LimitChange;
import dev.vality.liminator.LimitRequest; import dev.vality.liminator.LimitRequest;
import dev.vality.liminator.OperationAlreadyInFinalState; import dev.vality.liminator.OperationAlreadyInFinalState;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException; import org.apache.thrift.TException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.*; import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j @Slf4j
@Component @Component

View File

@ -1,5 +1,6 @@
package com.empayre.liminator.model; package com.empayre.liminator.model;
import com.empayre.liminator.domain.enums.OperationState;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@ -9,7 +10,6 @@ public class LimitValue {
private String limitId; private String limitId;
private String limitName; private String limitName;
private Long commitValue; private OperationState state;
private Long holdValue; private Long operationValue;
private Long rollbackValue;
} }

View File

@ -68,7 +68,9 @@ public class LiminatorService implements LiminatorServiceSrv.Iface {
throws LimitNotFound, LimitsValuesReadingException, TException { throws LimitNotFound, LimitsValuesReadingException, TException {
try { try {
log.info("Get limits with request: {}", request); log.info("Get limits with request: {}", request);
return getLimitsValuesHandler.handle(request); List<LimitResponse> limitResponses = getLimitsValuesHandler.handle(request);
log.info("Success get limit responses: {}", limitResponses);
return limitResponses;
} catch (DataAccessException ex) { } catch (DataAccessException ex) {
log.error("[GET] Received DaoException for getting limits operation (request: {})", request, ex); log.error("[GET] Received DaoException for getting limits operation (request: {})", request, ex);
throw new LimitsValuesReadingException(); throw new LimitsValuesReadingException();
@ -80,7 +82,9 @@ public class LiminatorService implements LiminatorServiceSrv.Iface {
throws LimitNotFound, LimitsValuesReadingException, TException { throws LimitNotFound, LimitsValuesReadingException, TException {
try { try {
log.info("Get last limits for limits: {}", Arrays.toString(limitNames.toArray())); log.info("Get last limits for limits: {}", Arrays.toString(limitNames.toArray()));
return getLastLimitsValuesHandler.handle(limitNames); List<LimitResponse> limitResponses = getLastLimitsValuesHandler.handle(limitNames);
log.info("Success get last limits response: {}", limitResponses);
return limitResponses;
} catch (DataAccessException ex) { } catch (DataAccessException ex) {
log.error("[GET] Received DaoException for getting last limits operation (limitNames: {})", limitNames, ex); log.error("[GET] Received DaoException for getting last limits operation (limitNames: {})", limitNames, ex);
throw new LimitsValuesReadingException(); throw new LimitsValuesReadingException();

View File

@ -34,11 +34,11 @@ public class LimitOperationsHistoryService {
} }
public List<LimitValue> getCurrentLimitValue(List<String> limitNames) { public List<LimitValue> getCurrentLimitValue(List<String> limitNames) {
return operationStateHistoryDao.getCurrentLimitValue(limitNames); return operationStateHistoryDao.getLimitHistory(limitNames);
} }
public List<LimitValue> getCurrentLimitValue(List<String> limitNames, String operationId) { public List<LimitValue> getCurrentLimitValue(List<String> limitNames, String operationId) {
return operationStateHistoryDao.getCurrentLimitValue(limitNames, operationId); return operationStateHistoryDao.getLimitHistory(limitNames, operationId);
} }
public List<OperationStateHistory> get(String operationId, public List<OperationStateHistory> get(String operationId,

View File

@ -0,0 +1,4 @@
DROP INDEX operation_history_idx;
CREATE INDEX operation_history_idx ON lim.operation_state_history USING btree (limit_data_id, state, created_at, operation_id);

View File

@ -7,15 +7,18 @@ import com.empayre.liminator.domain.tables.pojos.LimitData;
import com.empayre.liminator.domain.tables.pojos.OperationStateHistory; import com.empayre.liminator.domain.tables.pojos.OperationStateHistory;
import com.empayre.liminator.model.LimitValue; import com.empayre.liminator.model.LimitValue;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
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;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@Slf4j @Slf4j
@PostgresqlSpringBootITest @PostgresqlSpringBootITest
@ -57,35 +60,40 @@ class DaoTests {
@Test @Test
void operationDaoHistoryTest() { void operationDaoHistoryTest() {
List<String> limitNamesList = new ArrayList<>(); var limitsList = new ArrayList<Pair<String, Long>>();
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
String limitName = "Limit-odc-1-" + i; String limitName = "Limit-odc-1-" + i;
String limitId = "Limit-id-odc-1-" + i; String limitId = "Limit-id-odc-1-" + i;
limitDataDao.save(new LimitData(null, limitName, LocalDate.now(), LocalDateTime.now(), limitId)); Long id = limitDataDao.save(new LimitData(null, limitName, LocalDate.now(), LocalDateTime.now(), limitId));
limitNamesList.add(limitName); limitsList.add(Pair.of(limitName, id));
} }
List<OperationStateHistory> operations = new ArrayList<>(); List<OperationStateHistory> operations = new ArrayList<>();
String operationNameTemplate = "Operation-odc-1-%s"; String operationNameTemplate = "Operation-odc-1-%s";
for (String limitName : limitNamesList) { for (Pair<String, Long> limit : limitsList) {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
operations.add(createOperationHistory(limitName, operationNameTemplate.formatted(i))); operations.add(
createOperationHistory(
limit.getKey(),
limit.getValue(),
operationNameTemplate.formatted(i))
);
} }
} }
operationStateHistoryDao.saveBatch(operations); operationStateHistoryDao.saveBatch(operations);
List<String> limitNames = limitsList.stream().map(Pair::getKey).toList();
List<LimitValue> currentLimitValue = operationStateHistoryDao.getLimitHistory(limitNames);
assertEquals(operations.size(), currentLimitValue.size());
currentLimitValue.forEach(value -> assertEquals(100, value.getOperationValue()));
operations.clear(); operations.clear();
var commitLimits = limitsList.subList(0, 3);
List<LimitValue> currentLimitValue = operationStateHistoryDao.getCurrentLimitValue(limitNamesList);
assertEquals(limitNamesList.size(), currentLimitValue.size());
currentLimitValue.forEach(value -> assertEquals(0, value.getCommitValue()));
currentLimitValue.forEach(value -> assertEquals(0, value.getRollbackValue()));
currentLimitValue.forEach(value -> assertNotEquals(0, value.getHoldValue()));
currentLimitValue.forEach(value -> assertNotEquals(0, getTotal(value)));
List<String> commitLimitNames = limitNamesList.subList(0, 3);
String finalizeOperationName = operationNameTemplate.formatted(1); String finalizeOperationName = operationNameTemplate.formatted(1);
for (String limitName : commitLimitNames) { for (Pair<String, Long> commitLimit : commitLimits) {
var operationHistory = createOperationHistory( var operationHistory = createOperationHistory(
limitName, commitLimit.getKey(),
commitLimit.getValue(),
finalizeOperationName, finalizeOperationName,
LocalDateTime.now(), LocalDateTime.now(),
OperationState.COMMIT); OperationState.COMMIT);
@ -94,10 +102,11 @@ class DaoTests {
operationStateHistoryDao.saveBatch(operations); operationStateHistoryDao.saveBatch(operations);
operations.clear(); operations.clear();
List<String> rollbackLimitNames = limitNamesList.subList(4, 9); var rollbackLimits = limitsList.subList(4, 9);
for (String limitName : rollbackLimitNames) { for (Pair<String, Long> rollbackLimit : rollbackLimits) {
var operationHistory = createOperationHistory( var operationHistory = createOperationHistory(
limitName, rollbackLimit.getKey(),
rollbackLimit.getValue(),
finalizeOperationName, finalizeOperationName,
LocalDateTime.now(), LocalDateTime.now(),
OperationState.ROLLBACK); OperationState.ROLLBACK);
@ -106,69 +115,36 @@ class DaoTests {
operationStateHistoryDao.saveBatch(operations); operationStateHistoryDao.saveBatch(operations);
operations.clear(); operations.clear();
List<LimitValue> limitValuesAfterChanges = operationStateHistoryDao.getCurrentLimitValue(limitNamesList); List<LimitValue> limitValuesAfterChanges = operationStateHistoryDao.getLimitHistory(limitNames);
List<LimitValue> limitValuesWithCommitData = limitValuesAfterChanges.stream()
.filter(value -> value.getCommitValue() == 100
&& value.getHoldValue() == 500
&& value.getRollbackValue() == 0)
.toList();
assertEquals(3, limitValuesWithCommitData.size());
List<LimitValue> limitValuesAfterRollback = limitValuesAfterChanges.stream() List<LimitValue> operationsWithCommitData = limitValuesAfterChanges.stream()
.filter(value -> value.getHoldValue() == 500 .filter(value -> value.getState() == OperationState.COMMIT)
&& value.getCommitValue() == 0
&& value.getRollbackValue() == 100)
.toList(); .toList();
assertEquals(5, limitValuesAfterRollback.size()); assertEquals(commitLimits.size(), operationsWithCommitData.size());
List<LimitValue> limitValuesWithoutChanges = limitValuesAfterChanges.stream() List<LimitValue> operationsWithRollback = limitValuesAfterChanges.stream()
.filter(value -> value.getHoldValue() == 500 .filter(value -> value.getState() == OperationState.ROLLBACK)
&& value.getCommitValue() == 0
&& value.getRollbackValue() == 0)
.toList(); .toList();
assertEquals(2, limitValuesWithoutChanges.size()); assertEquals(rollbackLimits.size(), operationsWithRollback.size());
List<LimitValue> operationsWithHold = limitValuesAfterChanges.stream()
.filter(value -> value.getState() == OperationState.HOLD)
.toList();
assertEquals(currentLimitValue.size(), operationsWithHold.size());
} }
private long getTotal(LimitValue value) { private OperationStateHistory createOperationHistory(String limitName, Long id, String operationId) {
return value.getHoldValue() - value.getCommitValue() - value.getRollbackValue(); return createOperationHistory(limitName, id, operationId, LocalDateTime.now(), OperationState.HOLD);
}
@Test
void operationDaoCurrentLimitWithOperationIdTest() {
String limitName = "Limit-odc-2";
String limitId = "Limit-id-odc-2";
Long id = limitDataDao.save(new LimitData(null, limitName, LocalDate.now(), LocalDateTime.now(), limitId));
List<OperationStateHistory> operations = new ArrayList<>();
for (int i = 0; i < 10; i++) {
var operation = createOperationHistory(
limitName,
"Operation-odc-2-%s-%s".formatted(id, i),
LocalDateTime.now().minusMinutes(11L - i),
OperationState.HOLD);
operationStateHistoryDao.save(operation);
operations.add(operation);
}
List<LimitValue> valuesForFifthOperation =
operationStateHistoryDao.getCurrentLimitValue(List.of(limitName), operations.get(2).getOperationId());
LimitValue limitValue = valuesForFifthOperation.get(0);
assertEquals(300, getTotal(limitValue));
valuesForFifthOperation =
operationStateHistoryDao.getCurrentLimitValue(List.of(limitName), operations.get(5).getOperationId());
assertEquals(600, getTotal(valuesForFifthOperation.get(0)));
}
private OperationStateHistory createOperationHistory(String limitName, String operationId) {
return createOperationHistory(limitName, operationId, LocalDateTime.now(), OperationState.HOLD);
} }
private OperationStateHistory createOperationHistory(String limitName, private OperationStateHistory createOperationHistory(String limitName,
Long id,
String operationId, String operationId,
LocalDateTime createdAt, LocalDateTime createdAt,
OperationState state) { OperationState state) {
OperationStateHistory operation = new OperationStateHistory(); OperationStateHistory operation = new OperationStateHistory();
operation.setLimitName(limitName); operation.setLimitName(limitName);
operation.setLimitDataId(id);
operation.setOperationId(operationId); operation.setOperationId(operationId);
operation.setState(state); operation.setState(state);
operation.setOperationValue(100L); operation.setOperationValue(100L);

View File

@ -35,6 +35,7 @@ class LiminatorServiceTest {
); );
List<LimitResponse> response = liminatorService.hold(request); List<LimitResponse> response = liminatorService.hold(request);
assertEquals(limitName, response.get(0).getLimitName()); assertEquals(limitName, response.get(0).getLimitName());
assertEquals(limitId, response.get(0).getLimitId()); assertEquals(limitId, response.get(0).getLimitId());
assertEquals(holdValue, response.get(0).getTotalValue()); assertEquals(holdValue, response.get(0).getTotalValue());
@ -59,7 +60,7 @@ class LiminatorServiceTest {
@Test @Test
void limitNotFoundTest() { void limitNotFoundTest() {
String limitName = "TestLimitCommit"; String limitName = "TestLimitCommit";
String operationId = "OpComit"; String operationId = "Op-123";
LimitRequest holdRequest = new LimitRequest() LimitRequest holdRequest = new LimitRequest()
.setOperationId(operationId) .setOperationId(operationId)
.setLimitChanges(List.of(new LimitChange(limitName, 500L))); .setLimitChanges(List.of(new LimitChange(limitName, 500L)));
@ -70,7 +71,7 @@ class LiminatorServiceTest {
@Test @Test
void operationNotFoundWithNotExistHoldTest() throws TException { void operationNotFoundWithNotExistHoldTest() throws TException {
String limitName = "TestLimitCommit"; String limitName = "TestLimitCommit";
String operationId = "OpComit"; String operationId = "Op-123";
LimitRequest holdRequest = new LimitRequest() LimitRequest holdRequest = new LimitRequest()
.setOperationId(operationId) .setOperationId(operationId)
.setLimitChanges(List.of(new LimitChange(limitName, 500L))); .setLimitChanges(List.of(new LimitChange(limitName, 500L)));
@ -86,7 +87,7 @@ class LiminatorServiceTest {
void operationNotFoundWithNotExpectedHoldCountTest() throws TException { void operationNotFoundWithNotExpectedHoldCountTest() throws TException {
String firstLimitName = "TestLimit1"; String firstLimitName = "TestLimit1";
String secondLimitName = "TestLimit2"; String secondLimitName = "TestLimit2";
String operationId = "OpComit"; String operationId = "Op-123";
LimitRequest holdRequest = new LimitRequest() LimitRequest holdRequest = new LimitRequest()
.setOperationId(operationId) .setOperationId(operationId)
.setLimitChanges(List.of( .setLimitChanges(List.of(
@ -165,21 +166,28 @@ class LiminatorServiceTest {
@Test @Test
void commitValueTest() throws TException { void commitValueTest() throws TException {
String limitName = "TestLimitCommit"; String limitName = "TestLimitCommit";
String operationId = "OpComit"; String operationId = "Op-123";
String limitId = "limit_day_id"; String limitId = "limit_day_id";
LimitRequest holdRequest = new LimitRequest() LimitRequest holdRequest = new LimitRequest()
.setOperationId(operationId) .setOperationId(operationId)
.setLimitChanges(List.of(new LimitChange(limitName, 500L).setLimitId(limitId))); .setLimitChanges(List.of(new LimitChange(limitName, 500L).setLimitId(limitId)));
liminatorService.hold(holdRequest);
List<LimitResponse> holdResponses = liminatorService.hold(holdRequest);
assertEquals(1, holdResponses.size());
assertEquals(500, holdResponses.get(0).getTotalValue());
assertEquals(0, holdResponses.get(0).getCommitValue());
assertEquals(limitName, holdResponses.get(0).getLimitName());
liminatorService.commit(holdRequest); liminatorService.commit(holdRequest);
List<LimitResponse> limitResponses = liminatorService.getLastLimitsValues(List.of(limitName)); List<LimitResponse> commitResponses = liminatorService.getLastLimitsValues(List.of(limitName));
assertEquals(1, limitResponses.size()); assertEquals(1, commitResponses.size());
assertEquals(1000, limitResponses.get(0).getTotalValue()); assertEquals(0, commitResponses.get(0).getTotalValue());
assertEquals(500, limitResponses.get(0).getCommitValue()); assertEquals(500, commitResponses.get(0).getCommitValue());
assertEquals(limitName, limitResponses.get(0).getLimitName()); assertEquals(limitName, commitResponses.get(0).getLimitName());
assertEquals(limitId, limitResponses.get(0).getLimitId()); assertEquals(limitId, commitResponses.get(0).getLimitId());
} }
@Test @Test
@ -189,20 +197,26 @@ class LiminatorServiceTest {
LimitRequest holdRequest = new LimitRequest() LimitRequest holdRequest = new LimitRequest()
.setOperationId(operationId) .setOperationId(operationId)
.setLimitChanges(List.of(new LimitChange(limitName, 500L))); .setLimitChanges(List.of(new LimitChange(limitName, 500L)));
liminatorService.hold(holdRequest); List<LimitResponse> holdResponses = liminatorService.hold(holdRequest);
assertEquals(1, holdResponses.size());
assertEquals(500, holdResponses.get(0).getTotalValue());
assertEquals(0, holdResponses.get(0).getCommitValue());
assertEquals(limitName, holdResponses.get(0).getLimitName());
liminatorService.rollback(holdRequest); liminatorService.rollback(holdRequest);
List<LimitResponse> limitResponses = liminatorService.getLastLimitsValues(List.of(limitName)); List<LimitResponse> rollbackResponses = liminatorService.getLastLimitsValues(List.of(limitName));
assertEquals(1, limitResponses.size()); assertEquals(1, rollbackResponses.size());
assertEquals(0, limitResponses.get(0).getTotalValue()); assertEquals(0, rollbackResponses.get(0).getTotalValue());
assertEquals(0, limitResponses.get(0).getCommitValue()); assertEquals(0, rollbackResponses.get(0).getCommitValue());
assertEquals(limitName, limitResponses.get(0).getLimitName()); assertEquals(limitName, rollbackResponses.get(0).getLimitName());
} }
@Test @Test
void complexOperationsTest() throws TException { void complexOperationsTest() throws TException {
String limitName = "TestLimitRollback"; String limitName = "TestLimitComplex";
String operationId = "Op-112-%s"; String operationId = "Op-112-%s";
LimitRequest firstHoldRequest = new LimitRequest() LimitRequest firstHoldRequest = new LimitRequest()
.setOperationId(operationId.formatted(1)) .setOperationId(operationId.formatted(1))
@ -227,28 +241,28 @@ class LiminatorServiceTest {
List<LimitResponse> limitResponseAfterFourthHold = liminatorService.hold(fourthHoldRequest); List<LimitResponse> limitResponseAfterFourthHold = liminatorService.hold(fourthHoldRequest);
assertEquals(1, limitResponseAfterFourthHold.size()); assertEquals(1, limitResponseAfterFourthHold.size());
assertEquals(500, limitResponseAfterFourthHold.get(0).getTotalValue()); assertEquals(300, limitResponseAfterFourthHold.get(0).getTotalValue());
assertEquals(100, limitResponseAfterFourthHold.get(0).getCommitValue()); assertEquals(100, limitResponseAfterFourthHold.get(0).getCommitValue());
assertEquals(limitName, limitResponseAfterFourthHold.get(0).getLimitName()); assertEquals(limitName, limitResponseAfterFourthHold.get(0).getLimitName());
liminatorService.rollback(firstHoldRequest); liminatorService.rollback(firstHoldRequest);
LimitRequest fifthHoldRequest = new LimitRequest() LimitRequest fifthHoldRequest = new LimitRequest()
.setOperationId(operationId.formatted(4)) .setOperationId(operationId.formatted(5))
.setLimitChanges(List.of(new LimitChange(limitName, 100L))); .setLimitChanges(List.of(new LimitChange(limitName, 100L)));
liminatorService.hold(fifthHoldRequest); liminatorService.hold(fifthHoldRequest);
List<LimitResponse> limitResponses = liminatorService.hold(fifthHoldRequest); List<LimitResponse> limitResponses = liminatorService.hold(fifthHoldRequest);
assertEquals(1, limitResponses.size()); assertEquals(1, limitResponses.size());
assertEquals(500, limitResponses.get(0).getTotalValue()); assertEquals(300, limitResponses.get(0).getTotalValue());
assertEquals(100, limitResponses.get(0).getCommitValue()); assertEquals(100, limitResponses.get(0).getCommitValue());
assertEquals(limitName, limitResponses.get(0).getLimitName()); assertEquals(limitName, limitResponses.get(0).getLimitName());
List<LimitResponse> limitResponseAfterAllForFourthHold = liminatorService.hold(fourthHoldRequest); List<LimitResponse> limitResponseAfterAllForFourthHold = liminatorService.hold(fourthHoldRequest);
assertEquals(1, limitResponseAfterAllForFourthHold.size()); assertEquals(1, limitResponseAfterAllForFourthHold.size());
assertEquals(500, limitResponseAfterAllForFourthHold.get(0).getTotalValue()); assertEquals(300, limitResponseAfterAllForFourthHold.get(0).getTotalValue());
assertEquals(100, limitResponseAfterAllForFourthHold.get(0).getCommitValue()); assertEquals(100, limitResponseAfterAllForFourthHold.get(0).getCommitValue());
assertEquals(limitName, limitResponseAfterAllForFourthHold.get(0).getLimitName()); assertEquals(limitName, limitResponseAfterAllForFourthHold.get(0).getLimitName());
} }