fix via using hibernate.type.EnumType

This commit is contained in:
Anatoly Karlov 2023-08-17 17:17:07 +03:00
parent 70bdc24440
commit d935230736
12 changed files with 2000 additions and 27 deletions

10
postgres/limit_config.sql Normal file
View File

@ -0,0 +1,10 @@
insert into dw.limit_config (id, source_id, sequence_id, event_occured_at, event_created_at, limit_config_id,
processor_type, created_at, started_at, shard_size, time_range_type,
time_range_type_calendar, time_range_type_interval_amount, limit_context_type,
limit_type_turnover_metric, limit_type_turnover_metric_amount_currency, limit_scope,
limit_scope_types_json, description, operation_limit_behaviour, wtime, current)
values (6120792236196579268, 'yKgTJlTuuvsNhabwqVecL', 1425107996, '2023-05-14 16:02:11.000000',
'2012-01-27 02:29:04.000000', 'yXAu', 'hwxJxGZRhyNgBJ', '2018-10-29 10:35:27.000000',
'2020-11-15 13:02:57.000000', 1909803147901017503, 'calendar', 'week', 8140454181643711723,
'withdrawal_processing', 'amount', 'LxoGJPKJYFLjFFXlq', 'single', '[{"party":{}},{"shop":{}},{"identity":{}}]',
'NpxQDGXbSrTxhBBklgQdunT', 'addition', '2019-07-15 11:26:34.000000', true);

27
postgres/payment.sql Normal file
View File

@ -0,0 +1,27 @@
insert into dw.payment (id, event_created_at, invoice_id, payment_id, created_at, party_id, shop_id, domain_revision,
party_revision, amount, currency_code, make_recurrent, sequence_id, change_id, wtime,
external_id, payment_flow_type, payment_flow_on_hold_expiration, payment_flow_held_until)
values (3, '2023-10-09 15:43:44.000000', '3', 'paymentIdSecond', '2019-01-04 10:48:41.000000', 'daPWufsrbkkBUivLv', '1',
8085731140781100426, 6125294474981918314, -104693329082533944, 'usd', false, 1634819983926092859, 949456950,
'2026-10-30 20:11:34.000000', 'tZfZxkmELKsBTdFeRmxoGF', 'instant', 'mysMYZcUSOgXWAfJblN',
'2017-12-20 09:33:46.000000'),
(1, '2023-10-09 15:43:44.000000', '1', 'paymentIdSecond', '2019-01-04 10:48:41.000000', 'daPWufsrbkkBUivLv', '1',
8085731140781100426, 6125294474981918314, -104693329082533944, 'rub', false, 1634819983926092859, 949456950,
'2026-10-30 20:11:34.000000', 'tZfZxkmELKsBTdFeRmxoGF', 'instant', 'mysMYZcUSOgXWAfJblN',
'2017-12-20 09:33:46.000000'),
(-3381080188089491054, '2023-10-09 15:43:44.000000', 'invoiceIdSecond', 'paymentIdSecond',
'2019-01-04 10:48:41.000000', 'daPWufsrbkkBUivLv', '1', 8085731140781100426, 6125294474981918314,
-104693329082533944, 'cny', false, 1634819983926092859, 949456950, '2026-10-30 20:11:34.000000',
'tZfZxkmELKsBTdFeRmxoGF', 'instant', 'mysMYZcUSOgXWAfJblN', '2017-12-20 09:33:46.000000'),
(2, '2023-10-09 15:43:44.000000', '2', 'paymentIdSecond', '2019-01-04 10:48:41.000000', 'daPWufsrbkkBUivLv', '1',
8085731140781100426, 6125294474981918314, -104693329082533944, 'kzt', false, 1634819983926092859, 949456950,
'2026-10-30 20:11:34.000000', 'tZfZxkmELKsBTdFeRmxoGF', 'instant', 'mysMYZcUSOgXWAfJblN',
'2017-12-20 09:33:46.000000'),
(4, '2023-10-09 15:43:44.000000', '4', 'paymentIdSecond', '2019-01-04 10:48:41.000000', 'daPWufsrbkkBUivLv', '1',
8085731140781100426, 6125294474981918314, -104693329082533944, 'uah', false, 1634819983926092859, 949456950,
'2026-10-30 20:11:34.000000', 'tZfZxkmELKsBTdFeRmxoGF', 'instant', 'mysMYZcUSOgXWAfJblN',
'2017-12-20 09:33:46.000000'),
(-5366357297803388401, '2023-10-09 15:43:44.000000', 'invoiceIdFirst', 'paymentIdFirst',
'2029-02-06 22:55:17.000000', 'ARGchjVfYGyGeeksqauAHsalvPeKAPJ', '1', -828724786828459679, -9810754775864408,
7649097838834368530, 'eur', true, 2058481949268875467, -1249452424, '2029-12-28 23:59:13.000000', 'FHPK',
'hold', 'EZTxEjBrt', '2018-04-18 09:57:06.000000');

10
postgres/postgres.yml Normal file
View File

@ -0,0 +1,10 @@
version: '3'
services:
postgresql:
image: postgres:13
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: daway

1791
postgres/schema.sql Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
package dev.vality.exporter.limits.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class ObjectMapperConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
return new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(new JavaTimeModule())
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
}

View File

@ -1,14 +1,14 @@
package dev.vality.exporter.limits.entity; package dev.vality.exporter.limits.entity;
import dev.vality.exporter.limits.entity.naming.PostgresEnumType;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import javax.persistence.Column; import javax.persistence.*;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.io.Serializable; import java.io.Serializable;
@Entity @Entity
@ -17,13 +17,16 @@ import java.io.Serializable;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Table(name = "limit_config") @Table(name = "limit_config")
@TypeDef(name = "pgsql_enum", typeClass = PostgresEnumType.class)
public class LimitConfigEntity implements Serializable { public class LimitConfigEntity implements Serializable {
@EmbeddedId @EmbeddedId
private LimitConfigPk pk; private LimitConfigPk pk;
@Column(name = "time_range_type") @Column(name = "time_range_type")
private String timeRangType; @Enumerated(EnumType.STRING)
@Type(type = "pgsql_enum")
private TimeRangeType timeRangType;
@Column(name = "time_range_type_calendar") @Column(name = "time_range_type_calendar")
private String timeRangeTypeCalendar; private String timeRangeTypeCalendar;
@ -43,4 +46,7 @@ public class LimitConfigEntity implements Serializable {
@Column(name = "limit_scope_types_json") @Column(name = "limit_scope_types_json")
private String limitScopeTypesJson; private String limitScopeTypesJson;
@Column(name = "current")
private Boolean current;
} }

View File

@ -0,0 +1,6 @@
package dev.vality.exporter.limits.entity;
public enum TimeRangeType {
calendar,
interval
}

View File

@ -0,0 +1,27 @@
package dev.vality.exporter.limits.entity.naming;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.EnumType;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
public class PostgresEnumType extends EnumType {
@Override
public void nullSafeSet(
PreparedStatement st,
Object value,
int index,
SharedSessionContractImplementor session)
throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.OTHER);
return;
}
st.setObject(index, value.toString(), Types.OTHER);
}
}

View File

@ -108,7 +108,6 @@ public class CustomTag {
return Tag.of(OPERATION_LIMIT_BEHAVIOUR, operationLimitBehaviour); return Tag.of(OPERATION_LIMIT_BEHAVIOUR, operationLimitBehaviour);
} }
public static Tag limitScopeTypes(String limitScopeTypes) { public static Tag limitScopeTypes(String limitScopeTypes) {
return Tag.of(LIMIT_SCOPE_TYPES, limitScopeTypes); return Tag.of(LIMIT_SCOPE_TYPES, limitScopeTypes);
} }

View File

@ -2,6 +2,7 @@ package dev.vality.exporter.limits.repository;
import dev.vality.exporter.limits.entity.LimitConfigEntity; import dev.vality.exporter.limits.entity.LimitConfigEntity;
import dev.vality.exporter.limits.entity.LimitConfigPk; import dev.vality.exporter.limits.entity.LimitConfigPk;
import dev.vality.exporter.limits.entity.TimeRangeType;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
@ -13,11 +14,12 @@ import java.util.List;
@SuppressWarnings("LineLength") @SuppressWarnings("LineLength")
public interface LimitConfigRepository extends JpaRepository<LimitConfigEntity, LimitConfigPk> { public interface LimitConfigRepository extends JpaRepository<LimitConfigEntity, LimitConfigPk> {
@Query(value = "select lc " + @Query(value = "select l " +
"from LimitConfigEntity as lc " + "from LimitConfigEntity as l " +
"where lc.limit_config_id in :limitConfigIds " + "where l.pk.limitConfigId in :limitConfigIds " +
"and lc.time_range_type = :time_range_type " + "and l.timeRangType = :timeRangType " +
"and lc.current = true") "and l.current = true"
List<LimitConfigEntity> findAllUsingLimitConfigIdsAndTimeRangType(@Param("limitConfigIds") List<String> limitConfigIds, @Param("time_range_type") String timeRangType); )
List<LimitConfigEntity> findAllUsingLimitConfigIdsAndTimeRangType(@Param("limitConfigIds") List<String> limitConfigIds, @Param("timeRangType") TimeRangeType timeRangType);
} }

View File

@ -1,17 +1,23 @@
package dev.vality.exporter.limits.service; package dev.vality.exporter.limits.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.vality.exporter.limits.entity.LimitConfigEntity; import dev.vality.exporter.limits.entity.LimitConfigEntity;
import dev.vality.exporter.limits.entity.TimeRangeType;
import dev.vality.exporter.limits.model.CustomTag; import dev.vality.exporter.limits.model.CustomTag;
import dev.vality.exporter.limits.model.LimitsData; import dev.vality.exporter.limits.model.LimitsData;
import dev.vality.exporter.limits.model.Metric; import dev.vality.exporter.limits.model.Metric;
import dev.vality.exporter.limits.repository.LimitConfigRepository; import dev.vality.exporter.limits.repository.LimitConfigRepository;
import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags; import io.micrometer.core.instrument.Tags;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -21,13 +27,12 @@ import java.util.stream.Collectors;
@SuppressWarnings("LineLength") @SuppressWarnings("LineLength")
public class LimitsService { public class LimitsService {
private static final String CALENDAR = "calendar";
private final MeterRegistryService meterRegistryService; private final MeterRegistryService meterRegistryService;
private final Map<String, Double> limitsBoundaryAggregatesMap; private final Map<String, Double> limitsBoundaryAggregatesMap;
private final Map<String, Double> limitsAmountAggregatesMap; private final Map<String, Double> limitsAmountAggregatesMap;
private final OpenSearchService openSearchService; private final OpenSearchService openSearchService;
private final LimitConfigRepository limitConfigRepository; private final LimitConfigRepository limitConfigRepository;
private final ObjectMapper objectMapper;
public void registerMetrics() { public void registerMetrics() {
var limitsDataByInterval = openSearchService.getLimitsDataByInterval(); var limitsDataByInterval = openSearchService.getLimitsDataByInterval();
@ -37,7 +42,7 @@ public class LimitsService {
.distinct() .distinct()
.toList(); .toList();
log.info("limitConfigIds {}", limitConfigIds); log.info("limitConfigIds {}", limitConfigIds);
var limitConfigEntities = limitConfigRepository.findAllUsingLimitConfigIdsAndTimeRangType(limitConfigIds, CALENDAR); var limitConfigEntities = limitConfigRepository.findAllUsingLimitConfigIdsAndTimeRangType(limitConfigIds, TimeRangeType.calendar);
log.info("limitConfigEntities {}", limitConfigEntities); log.info("limitConfigEntities {}", limitConfigEntities);
var limitConfigsById = limitConfigEntities.stream().collect( var limitConfigsById = limitConfigEntities.stream().collect(
Collectors.groupingBy( Collectors.groupingBy(
@ -67,7 +72,7 @@ public class LimitsService {
gauge(limitsAmountAggregatesMap, Metric.LIMITS_AMOUNT, id, getTags(limitsData, limitConfigEntity), limitsData.getLimit().getAmount()); gauge(limitsAmountAggregatesMap, Metric.LIMITS_AMOUNT, id, getTags(limitsData, limitConfigEntity), limitsData.getLimit().getAmount());
} }
var registeredMetricsSize = meterRegistryService.getRegisteredMetricsSize(Metric.LIMITS_BOUNDARY.getName()) + meterRegistryService.getRegisteredMetricsSize(Metric.LIMITS_AMOUNT.getName()); var registeredMetricsSize = meterRegistryService.getRegisteredMetricsSize(Metric.LIMITS_BOUNDARY.getName()) + meterRegistryService.getRegisteredMetricsSize(Metric.LIMITS_AMOUNT.getName());
log.info("Limits with final statuses metrics have been registered to 'prometheus', " + log.info("Limits metrics have been registered to 'prometheus', " +
"registeredMetricsSize = {}, clientSize = {}", registeredMetricsSize, limitsDataByInterval.size()); "registeredMetricsSize = {}, clientSize = {}", registeredMetricsSize, limitsDataByInterval.size());
} }
@ -83,16 +88,27 @@ public class LimitsService {
private Tags getTags(LimitsData dto, LimitConfigEntity limitConfigEntity) { private Tags getTags(LimitsData dto, LimitConfigEntity limitConfigEntity) {
return Tags.of( return Tags.of(
CustomTag.terminalId(dto.getLimit().getRoute().getTerminalId()), CustomTag.terminalId(dto.getLimit().getRoute().getTerminalId()),
CustomTag.providerId(dto.getLimit().getRoute().getProviderId()), CustomTag.providerId(dto.getLimit().getRoute().getProviderId()),
CustomTag.currency(dto.getLimit().getChange().getCurrency()), CustomTag.currency(dto.getLimit().getChange().getCurrency()),
CustomTag.shopId(dto.getLimit().getShopId()), CustomTag.shopId(dto.getLimit().getShopId()),
CustomTag.configId(dto.getLimit().getConfigId()), CustomTag.configId(dto.getLimit().getConfigId()),
CustomTag.timeRangType(limitConfigEntity.getTimeRangType()), CustomTag.timeRangType(limitConfigEntity.getTimeRangType().name()),
CustomTag.timeRangeTypeCalendar(limitConfigEntity.getTimeRangeTypeCalendar()), CustomTag.timeRangeTypeCalendar(limitConfigEntity.getTimeRangeTypeCalendar()),
CustomTag.limitContextType(limitConfigEntity.getLimitContextType()), CustomTag.limitContextType(limitConfigEntity.getLimitContextType()),
CustomTag.limitTypeTurnoverMetric(limitConfigEntity.getLimitTypeTurnoverMetric()), CustomTag.limitTypeTurnoverMetric(limitConfigEntity.getLimitTypeTurnoverMetric()),
CustomTag.limitScope(limitConfigEntity.getLimitScope()), CustomTag.limitScope(limitConfigEntity.getLimitScope()),
CustomTag.operationLimitBehaviour(limitConfigEntity.getOperationLimitBehaviour())); CustomTag.operationLimitBehaviour(limitConfigEntity.getOperationLimitBehaviour()))
.and(getLimitScopeTypeTags(limitConfigEntity.getLimitScopeTypesJson()));
}
@SneakyThrows
private List<Tag> getLimitScopeTypeTags(String limitScopeTypesJson) {
return objectMapper.readValue(limitScopeTypesJson, new TypeReference<List<Map<String, Object>>>() {
})
.stream()
.flatMap(stringObjectMap -> stringObjectMap.keySet().stream())
.map(s -> Tag.of(String.format("limit_scope_type_%s", s), "true"))
.collect(Collectors.toList());
} }
} }

View File

@ -0,0 +1,55 @@
package dev.vality.exporter.limits;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.vality.exporter.limits.entity.TimeRangeType;
import dev.vality.exporter.limits.repository.LimitConfigRepository;
import io.micrometer.core.instrument.Tag;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.opensearch.client.RestClient;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.TestPropertySource;
import java.util.List;
import java.util.Map;
@SpringBootTest
@TestPropertySource({"classpath:application.yml"})
@DirtiesContext
@Slf4j
@Disabled
@SuppressWarnings("LineLength")
public class LimitConfigRepositoryTest {
@MockBean
private RestClient restClient;
@MockBean
private OpenSearchClient openSearchClient;
@Autowired
private LimitConfigRepository limitConfigRepository;
@Test
@SneakyThrows
public void findAllUsingLimitConfigIdsAndTimeRangTypeTest() {
var limitConfigEntities = limitConfigRepository.findAllUsingLimitConfigIdsAndTimeRangType(List.of("yXAu"), TimeRangeType.calendar);
var limitConfigEntity = limitConfigEntities.get(0);
Assertions.assertEquals(1425107996, limitConfigEntity.getPk().getSequenceId());
var tags = new ObjectMapper().readValue(limitConfigEntity.getLimitScopeTypesJson(), new TypeReference<List<Map<String, Object>>>() {
})
.stream()
.flatMap(stringObjectMap -> stringObjectMap.keySet().stream())
.map(s -> Tag.of(String.format("limit_scope_type_%s", s), "true"))
.toList();
Assertions.assertEquals(3, tags.size());
}
}