From fae7a374245506ad340e0ec1cf05146da67d610c Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Thu, 28 Sep 2023 14:19:26 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-522 --- clearing-parent/imdg-hist/pom.xml | 173 ++++++++++++++++++ .../historyimdg/IMDGHistApplication.java | 12 ++ .../config/HistoryDbConnectionConfig.java | 71 +++++++ .../config/HistoryHazelcastConfiguration.java | 62 +++++++ .../config/HistoryPoolMapConfigs.java | 94 ++++++++++ .../config/element/ControllerSettings.java | 25 +++ .../config/element/DatabaseSettings.java | 31 ++++ .../element/HazelcastServerSettings.java | 43 +++++ .../config/element/ImdgSettings.java | 38 ++++ .../historyimdg/index/SearchProxy.java | 29 +++ .../index/SearchProxyRegistry.java | 24 +++ .../index/field/SearchCompanyId.java | 7 + .../historyimdg/index/field/SearchWithId.java | 7 + .../index/field/SearchWithTradingDay.java | 9 + .../mapstores/AbstractSliceMapLoader.java | 95 ++++++++++ .../historyimdg/mapstores/HistMapStore.java | 4 + .../mapstores/HistoryMapConfig.java | 63 +++++++ .../mapstores/RegistryHistoryMapStore.java | 31 ++++ .../mapstores/SearchRegistryMapStore.java | 45 +++++ .../src/main/resources/application.properties | 12 ++ .../src/main/resources/hazelcast.yaml | 5 + .../imdg-hist/src/main/resources/logback.xml | 38 ++++ .../imdg/base/AutoconfiguredMap1.java | 17 ++ clearing-parent/pom.xml | 1 + .../clearing/imdg/IMDGDistributedNames.java | 2 + pom.xml | 5 + 26 files changed, 943 insertions(+) create mode 100644 clearing-parent/imdg-hist/pom.xml create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/IMDGHistApplication.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryDbConnectionConfig.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryHazelcastConfiguration.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryPoolMapConfigs.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/ControllerSettings.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/DatabaseSettings.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/HazelcastServerSettings.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/ImdgSettings.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/SearchProxy.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/SearchProxyRegistry.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchCompanyId.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchWithId.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchWithTradingDay.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/AbstractSliceMapLoader.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/HistMapStore.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/HistoryMapConfig.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/RegistryHistoryMapStore.java create mode 100644 clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/SearchRegistryMapStore.java create mode 100644 clearing-parent/imdg-hist/src/main/resources/application.properties create mode 100644 clearing-parent/imdg-hist/src/main/resources/hazelcast.yaml create mode 100644 clearing-parent/imdg-hist/src/main/resources/logback.xml create mode 100644 clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/base/AutoconfiguredMap1.java diff --git a/clearing-parent/imdg-hist/pom.xml b/clearing-parent/imdg-hist/pom.xml new file mode 100644 index 000000000..b97f12c19 --- /dev/null +++ b/clearing-parent/imdg-hist/pom.xml @@ -0,0 +1,173 @@ + + + 4.0.0 + + clearing-parent + ru.spcex.clearing + SPCEX-1.0.0.0 + + + imdg-hist + jar + + + 17 + 17 + UTF-8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-autoconfigure + + + ru.spcex.clearing + imdg + SPCEX-1.0.0.0 + + + ru.spcex.clearing + classes + SPCEX-1.0.0.0 + compile + + + ru.spcex.clearing + dictionary + SPCEX-1.0.0.0 + compile + + + + + + org.springframework + spring-jdbc + + + org.postgresql + postgresql + + + com.mchange + c3p0 + + + + + com.hazelcast + hazelcast-all + ${external_libraries.hazelcast.version} + + + ru.spcex.platform + platform-imdg-api + + + ru.spcex.platform + platform-imdg-api-hazelcast-impl + + + ru.spcex.platform + platform-enum + + + ru.spcex.clearing + cleaning-builders + SPCEX-1.0.0.0 + compile + + + ru.spcex.clearing + clearing-validation + + + + + org.springframework + spring-test + test + + + org.skyscreamer + jsonassert + test + + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + test + + + + + + + src/main/resources + + application.properties + + false + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + ru.spcex.clearing.historyimdg.IMDGHistApplication + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + true + exec + ${project.artifactId} + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.21.0 + + + org.junit.platform + junit-platform-surefire-provider + 1.2.0-M1 + + + org.junit.jupiter + junit-jupiter-engine + 5.2.0-M1 + + + + + + \ No newline at end of file diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/IMDGHistApplication.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/IMDGHistApplication.java new file mode 100644 index 000000000..46f6ad798 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/IMDGHistApplication.java @@ -0,0 +1,12 @@ +package ru.spcex.clearing.historyimdg; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class IMDGHistApplication { + public static void main(String[] args) { + SpringApplicationBuilder builder = new SpringApplicationBuilder(IMDGHistApplication.class); + builder.run(args); + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryDbConnectionConfig.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryDbConnectionConfig.java new file mode 100644 index 000000000..aefce5aa1 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryDbConnectionConfig.java @@ -0,0 +1,71 @@ +package ru.spcex.clearing.historyimdg.config; + +import com.mchange.v2.c3p0.ComboPooledDataSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import ru.spcex.clearing.historyimdg.config.element.DatabaseSettings; +import ru.spcex.clearing.historyimdg.config.element.ImdgSettings; +import ru.spcex.clearing.imdg.error.ModuleInitializeException; + +import javax.sql.DataSource; +import java.sql.Connection; + +@SuppressWarnings("UnnecessaryLocalVariable") +@Configuration +public class HistoryDbConnectionConfig { + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + private final DatabaseSettings settings; + + public HistoryDbConnectionConfig(ImdgSettings settings) { + this.settings = settings.getDatabase(); + } + + @Bean(destroyMethod = "close") + public ComboPooledDataSource dataSource() { + String login = settings.getLogin(); + String password = settings.getPassword(); + String logTimeoutPart = ""; + String dbPath = settings.getUrl(); + int timeoutSec = 30; + + ComboPooledDataSource cpds = new ComboPooledDataSource(); + try { + cpds.setDriverClass("org.postgresql.Driver"); + } catch (Exception ue) { + throw new RuntimeException(ue); + } + cpds.setJdbcUrl(dbPath); + cpds.setUser(login); + cpds.setPassword(password); + cpds.setInitialPoolSize(10); + cpds.setMinPoolSize(10); + cpds.setMaxPoolSize(30); + int numHelperThreads = Runtime.getRuntime().availableProcessors() * 2; + cpds.setNumHelperThreads(numHelperThreads); + cpds.setCheckoutTimeout(timeoutSec * 1000); + logTimeoutPart = String.format(" (timeout=%ds)", timeoutSec); + + String OPERATION_DATABASE_CONNECTION_CHECK = String.format("Database [%s] connection check", dbPath); + try { + Connection conn = cpds.getConnection(); + conn.close(); + log.info("{}: success", OPERATION_DATABASE_CONNECTION_CHECK); + return cpds; + } catch (Throwable e) { + String msg = String.format("%s%s: failed: %s -> %s", + OPERATION_DATABASE_CONNECTION_CHECK, logTimeoutPart, e.getClass().getSimpleName(), e.getMessage()); + log.error(msg); + throw new ModuleInitializeException(msg, e); + } + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); + return jdbcTemplate; + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryHazelcastConfiguration.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryHazelcastConfiguration.java new file mode 100644 index 000000000..9b5b5c990 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryHazelcastConfiguration.java @@ -0,0 +1,62 @@ +package ru.spcex.clearing.historyimdg.config; + +import com.hazelcast.config.*; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import ru.spcex.clearing.historyimdg.config.element.HazelcastServerSettings; +import ru.spcex.clearing.historyimdg.config.element.ImdgSettings; + +import java.util.List; + +@Configuration +public class HistoryHazelcastConfiguration { + + private final HistoryPoolMapConfigs poolMapConfigs; + private final HazelcastServerSettings hzSettings; + + @Autowired + public HistoryHazelcastConfiguration(HistoryPoolMapConfigs poolMapConfigs, + ImdgSettings imdgSettings) { + this.poolMapConfigs = poolMapConfigs; + this.hzSettings = imdgSettings.getHazelcast(); + } + + @Bean("hazelcastInstanceImdg") + public HazelcastInstance hazelcastServerInstance(Config config) { + return Hazelcast.newHazelcastInstance(config); + } + + @Bean + public Config hazelCastConfig() { + Config config = new Config(); + config.setInstanceName("instance"); + config.setGroupConfig(new GroupConfig() + .setName(hzSettings.getLogin()) + .setPassword(hzSettings.getPassword()) + ); + config.setProperty("hazelcast.shutdownhook.enabled", "true"); + config.setProperty("hazelcast.logging.type", "slf4j"); + config.setProperty("hazelcast.operation.call.timeout.millis", "600000"); + config.setNetworkConfig(new NetworkConfig() + .setPort(hzSettings.getListenPort()) + .setJoin(new JoinConfig() + .setMulticastConfig(new MulticastConfig() + .setEnabled(false)) + .setTcpIpConfig(new TcpIpConfig() + .setEnabled(true).setMembers(hzSettings.getClusterMembers()) + ) + ) + ); + + List autoMapCfg = poolMapConfigs.configureEachMapStore(); + for (MapConfig cfg : autoMapCfg) { + config.addMapConfig(cfg); + } + return config; + } + + +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryPoolMapConfigs.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryPoolMapConfigs.java new file mode 100644 index 000000000..dcd4012b0 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/HistoryPoolMapConfigs.java @@ -0,0 +1,94 @@ +package ru.spcex.clearing.historyimdg.config; + +import com.hazelcast.config.*; +import com.hazelcast.core.MapLoader; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import ru.spcex.clearing.imdg.base.AutoconfiguredMap1; +import ru.spcex.clearing.imdg.base.DictionaryTMapStore; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +@Configuration +public class HistoryPoolMapConfigs { + private final Logger log = LoggerFactory.getLogger(getClass()); + + + private final List> autoconfiguredMaps; + + @Autowired + public HistoryPoolMapConfigs(List> autoconfiguredMaps) { + this.autoconfiguredMaps = autoconfiguredMaps; + } + + private MapStoreConfig makeDefaultMapStoreConfig(MapLoader mapBean) { + return new MapStoreConfig() + .setImplementation(mapBean); + } + + + public MapConfig makeDefaultMapConfig(String mapName, MapLoader mapBean) { + return new MapConfig() + .setName(mapName) + .setInMemoryFormat(InMemoryFormat.OBJECT) + .setMapStoreConfig(makeDefaultMapStoreConfig(mapBean)); + } + + private NearCacheConfig makeDefaultNearCacheConfig() { + return new NearCacheConfig() + .setMaxIdleSeconds(3600) + .setInMemoryFormat(InMemoryFormat.OBJECT) + .setSerializeKeys(true); + } + + private MapIndexConfig makeMapIndexConfig(String attributeName, boolean ordered) { + return new MapIndexConfig() + .setAttribute(attributeName) + .setOrdered(ordered); + } + + private MapIndexConfig makeMapIndexConfig(String attributeName) { + return makeMapIndexConfig(attributeName, false); + } + + public List configureEachMapStore() { + List out = new ArrayList<>(); + HashSet existMapStores = new HashSet<>(); + for (AutoconfiguredMap1 mapStore : autoconfiguredMaps) { + try { + log.debug("Link mapstore {} to map {}", mapStore.toString(), mapStore.getMapName()); + if (StringUtils.isEmpty(mapStore.getMapName())) { + throw new IllegalArgumentException("MapStore " + mapStore + " has empty mapName"); + } + if (existMapStores.contains(mapStore.getMapName())) { + throw new IllegalArgumentException("MapStore " + mapStore + " has wrong mapName=\"" + mapStore.getMapName() + "\" is duplicated"); + } + existMapStores.add(mapStore.getMapName()); // IMDGDistributedNames + MapConfig mapCfg = makeDefaultMapConfig(mapStore.getMapName(), mapStore); + if (mapStore.getIndexingField() != null && mapStore.getIndexingField().length > 0) { + if (log.isTraceEnabled()) { + log.trace("Create indexing filed on {}: {}", mapStore.getMapName(), Arrays.toString(mapStore.getIndexingField())); + } + for (String indexName : mapStore.getIndexingField()) { + mapCfg.addMapIndexConfig(makeMapIndexConfig(indexName)); + } + } + if (mapStore instanceof DictionaryTMapStore) { + log.trace("Use near cache for {}", mapStore.getMapName()); + mapCfg.setNearCacheConfig(makeDefaultNearCacheConfig()); + } + out.add(mapCfg); + } catch (RuntimeException e) { + throw new RuntimeException("Can not configure MapStore " + mapStore.getMapName() + "(" + mapStore + "): " + e, e); + } + } + log.debug("Configured {} mapStore's", out.size()); + return out; + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/ControllerSettings.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/ControllerSettings.java new file mode 100644 index 000000000..7ffe3144b --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/ControllerSettings.java @@ -0,0 +1,25 @@ +package ru.spcex.clearing.historyimdg.config.element; + +/** + * Debug config + */ +public class ControllerSettings { + private String port; + private String contextPath; + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getContextPath() { + return contextPath; + } + + public void setContextPath(String contextPath) { + this.contextPath = contextPath; + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/DatabaseSettings.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/DatabaseSettings.java new file mode 100644 index 000000000..ee8495f65 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/DatabaseSettings.java @@ -0,0 +1,31 @@ +package ru.spcex.clearing.historyimdg.config.element; + +public class DatabaseSettings { + private String login; + private String password; + private String url; + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/HazelcastServerSettings.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/HazelcastServerSettings.java new file mode 100644 index 000000000..05af0a7ef --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/HazelcastServerSettings.java @@ -0,0 +1,43 @@ +package ru.spcex.clearing.historyimdg.config.element; + +import java.util.List; + +public class HazelcastServerSettings { + + private int listenPort = 5701; + private String login; + private String password; + private List clusterMembers; + + public int getListenPort() { + return listenPort; + } + + public void setListenPort(int listenPort) { + this.listenPort = listenPort; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public List getClusterMembers() { + return clusterMembers; + } + + public void setClusterMembers(List clusterMembers) { + this.clusterMembers = clusterMembers; + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/ImdgSettings.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/ImdgSettings.java new file mode 100644 index 000000000..d3bf410b2 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/config/element/ImdgSettings.java @@ -0,0 +1,38 @@ +package ru.spcex.clearing.historyimdg.config.element; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component +@PropertySource("file:${spring.config.location}/application.properties") +@ConfigurationProperties("imdg.hist") +public class ImdgSettings { + private HazelcastServerSettings hazelcast; + private DatabaseSettings database; + private ControllerSettings debugServer; + + public HazelcastServerSettings getHazelcast() { + return hazelcast; + } + + public void setHazelcast(HazelcastServerSettings hazelcast) { + this.hazelcast = hazelcast; + } + + public DatabaseSettings getDatabase() { + return database; + } + + public void setDatabase(DatabaseSettings database) { + this.database = database; + } + + public ControllerSettings getDebugServer() { + return debugServer; + } + + public void setDebugServer(ControllerSettings debugServer) { + this.debugServer = debugServer; + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/SearchProxy.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/SearchProxy.java new file mode 100644 index 000000000..0eb4fee26 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/SearchProxy.java @@ -0,0 +1,29 @@ +package ru.spcex.clearing.historyimdg.index; + + +import ru.spcex.clearing.historyimdg.index.field.SearchWithId; +import ru.spcex.clearing.historyimdg.index.field.SearchWithTradingDay; +import ru.spcex.platform.classes.base.SpcexObjectBase; + +import java.time.LocalDate; + +public class SearchProxy extends SpcexObjectBase implements SearchWithTradingDay, SearchWithId { + private LocalDate tradingDate; + + @Override + public LocalDate getTradingDate() { + return tradingDate; + } + + @Override + public void setTradingDate(LocalDate tradingDate) { + this.tradingDate = tradingDate; + } + + @Override + public String toString() { + return "SearchProxy{" + + ", id=" + id + + '}'; + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/SearchProxyRegistry.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/SearchProxyRegistry.java new file mode 100644 index 000000000..d6ed646ee --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/SearchProxyRegistry.java @@ -0,0 +1,24 @@ +package ru.spcex.clearing.historyimdg.index; + +import ru.spcex.clearing.historyimdg.index.field.SearchCompanyId; + +import java.time.LocalDate; + +public class SearchProxyRegistry extends SearchProxy implements SearchCompanyId { + private Long companyId; + + @Override + public Long getCompanyId() { + return companyId; + } + + @Override + public void setCompanyId(Long companyId) { + this.companyId = companyId; + } + + @Override + public void setTradingDate(LocalDate tradingDate) { + + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchCompanyId.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchCompanyId.java new file mode 100644 index 000000000..e148c4530 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchCompanyId.java @@ -0,0 +1,7 @@ +package ru.spcex.clearing.historyimdg.index.field; + +public interface SearchCompanyId { + Long getCompanyId(); + + void setCompanyId(Long id); +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchWithId.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchWithId.java new file mode 100644 index 000000000..01453c73e --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchWithId.java @@ -0,0 +1,7 @@ +package ru.spcex.clearing.historyimdg.index.field; + +public interface SearchWithId { + Long getId(); + + void setId(Long id); +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchWithTradingDay.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchWithTradingDay.java new file mode 100644 index 000000000..f1cd6f3b8 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/index/field/SearchWithTradingDay.java @@ -0,0 +1,9 @@ +package ru.spcex.clearing.historyimdg.index.field; + +import java.time.LocalDate; + +public interface SearchWithTradingDay { + LocalDate getTradingDate(); + + void setTradingDate(LocalDate tradingDate); +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/AbstractSliceMapLoader.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/AbstractSliceMapLoader.java new file mode 100644 index 000000000..37c2005ac --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/AbstractSliceMapLoader.java @@ -0,0 +1,95 @@ +package ru.spcex.clearing.historyimdg.mapstores; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.support.DataAccessUtils; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import ru.spcex.clearing.imdg.base.AutoconfiguredMap; +import ru.spcex.platform.classes.base.interfaces.WithId; + +import java.sql.Date; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.*; + +import static ru.spcex.clearing.imdg.base.ObjectBaseMapStore.MAX_IN_CLAUSE_SIZE; + +public abstract class AbstractSliceMapLoader implements AutoconfiguredMap { + protected final Logger log = LoggerFactory.getLogger(getClass()); + + protected NamedParameterJdbcTemplate namedParameterJdbcTemplate; + protected JdbcTemplate jdbcTemplate; + protected final DateTimeFormatter FIREBIRD_INSTANT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()); + + public AbstractSliceMapLoader(JdbcTemplate jdbcTemplate) { + this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate); + this.jdbcTemplate = jdbcTemplate; + } + + protected abstract String getTableName(); + + @Override + public T load(Long id) { + Collection rows; + List list = Collections.singletonList(id); + try { + rows = load(list); + } catch (Throwable e) { // one retry + rows = load(list); + } + return DataAccessUtils.singleResult(rows); + } + + @SuppressWarnings("Duplicates") + @Override + public Map loadAll(Collection keys) { + log.debug("loadAll from " + getTableName() + " " + keys.size() + " keys"); + Map result = new HashMap<>(); + long start = System.currentTimeMillis(); + + // загрузить данные по ключам частями, чтобы не выйти за ограничения базы по кол-ву элементов в in clause + List keysSubList = new ArrayList<>(MAX_IN_CLAUSE_SIZE); + for (Iterator iterator = keys.iterator(); iterator.hasNext(); ) { + Long key = iterator.next(); + keysSubList.add(key); + if (keysSubList.size() == MAX_IN_CLAUSE_SIZE || !iterator.hasNext()) { + Collection rows = load(keysSubList); + for (T row : rows) { + result.put(row.getId(), row); + } + keysSubList.clear(); + } + } + + log.debug("loadAll from " + getTableName() + " " + keys.size() + " keys done in " + (System.currentTimeMillis() - start) + "ms"); + + return result; + + } + + @Override + public Iterable loadAllKeys() { + log.debug("loading all keys from {}...", getTableName()); + Instant yesterdayInstant = Instant.now().minus(0, ChronoUnit.DAYS); + Instant halfYearAgo = yesterdayInstant.minus(365, ChronoUnit.DAYS); + List ids = jdbcTemplate.query("select id from " + getTableName() + " where CAST(tradingday as DATE) <= ? and CAST(tradingday as DATE) >= ? ", + new Object[]{FIREBIRD_INSTANT_FORMATTER.format(yesterdayInstant), FIREBIRD_INSTANT_FORMATTER.format(halfYearAgo)}, + (resultSet, i) -> resultSet.getObject("id", Long.class)); + log.debug("loading all keys from {} done; size={}", getTableName(), ids.size()); + return ids; + } + + protected LocalDate getLocalDateFromSqlDate(ResultSet rs, String column) throws SQLException { + Date date = rs.getDate(column); + return date != null ? date.toLocalDate() : null; + } + + protected abstract Collection load(Collection keys); + +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/HistMapStore.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/HistMapStore.java new file mode 100644 index 000000000..cff0d8d31 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/HistMapStore.java @@ -0,0 +1,4 @@ +package ru.spcex.clearing.historyimdg.mapstores; + +public interface HistMapStore { +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/HistoryMapConfig.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/HistoryMapConfig.java new file mode 100644 index 000000000..9164c2c68 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/HistoryMapConfig.java @@ -0,0 +1,63 @@ +package ru.spcex.clearing.historyimdg.mapstores; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; + +@Configuration +public class HistoryMapConfig { + + private final JdbcTemplate jdbcTemplate; + + @Autowired + public HistoryMapConfig(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + +// @Bean +// public AutoconfiguredMap registryHistMapStore() { +// return new RegistryMapStore(jdbcTemplate) { +// @Override +// protected boolean isLoadable(Long id) { +// return true; +// } +// +// @Override +// protected boolean isLoadable(Registry obj) { +// return true; +// } +// +// @Override +// public Iterable loadAllKeys() { +// log.debug("RegistryHistoryMapStore loadAllKeys is called"); +// return new ArrayList<>(); +// } +// }; +// } +// +// @Bean +// public AutoconfiguredMap registrySomeMapStore(Class> cl) { +// try { +// AutoconfiguredMap map = cl.getDeclaredConstructor().newInstance(jdbcTemplate); +// } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { +// throw new RuntimeException(e); +// } +// return new RegistryMapStore(jdbcTemplate) { +// @Override +// protected boolean isLoadable(Long id) { +// return true; +// } +// +// @Override +// protected boolean isLoadable(Registry obj) { +// return true; +// } +// +// @Override +// public Iterable loadAllKeys() { +// log.debug("RegistryHistoryMapStore loadAllKeys is called"); +// return new ArrayList<>(); +// } +// }; +// } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/RegistryHistoryMapStore.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/RegistryHistoryMapStore.java new file mode 100644 index 000000000..dc180ddef --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/RegistryHistoryMapStore.java @@ -0,0 +1,31 @@ +package ru.spcex.clearing.historyimdg.mapstores; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.registry.Registry; +import ru.spcex.clearing.imdg.businessobject.RegistryMapStore; + +import java.util.ArrayList; + +@Component +public class RegistryHistoryMapStore extends RegistryMapStore { + public RegistryHistoryMapStore(JdbcTemplate jdbcTemplate) { + super(jdbcTemplate); + } + + @Override + protected boolean isLoadable(Long id) { + return true; + } + + @Override + protected boolean isLoadable(Registry obj) { + return true; + } + + @Override + public Iterable loadAllKeys() { + log.debug("RegistryHistoryMapStore loadAllKeys is called"); + return new ArrayList<>(); + } +} diff --git a/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/SearchRegistryMapStore.java b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/SearchRegistryMapStore.java new file mode 100644 index 000000000..64ca0f478 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/java/ru/spcex/clearing/historyimdg/mapstores/SearchRegistryMapStore.java @@ -0,0 +1,45 @@ +package ru.spcex.clearing.historyimdg.mapstores; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; +import ru.spcex.clearing.historyimdg.index.SearchProxyRegistry; +import ru.spcex.clearing.imdg.IMDGDistributedNames; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +@Component +public class SearchRegistryMapStore extends AbstractSliceMapLoader { + public SearchRegistryMapStore(JdbcTemplate jdbcTemplate) { + super(jdbcTemplate); + } + + @Override + protected String getTableName() { + return "registry"; + } + + @Override + public Collection load(Collection keys) { + Map> paramMap = Collections.singletonMap("ids", keys); + return namedParameterJdbcTemplate.query("select * from " + getTableName() + " where id in (:ids)", paramMap, + (rs, rowNum) -> { + SearchProxyRegistry proxyRegistry = new SearchProxyRegistry(); + proxyRegistry.setId(rs.getObject("id", Long.class)); + proxyRegistry.setTradingDate(getLocalDateFromSqlDate(rs,"trading_date")); + proxyRegistry.setCompanyId(rs.getObject("company_id", Long.class)); + return proxyRegistry; + }); + } + + @Override + public String getMapName() { + return IMDGDistributedNames.Map_SearchRegistry; + } + + @Override + public String[] getIndexingField() { + return new String[]{"companyId"}; + } +} diff --git a/clearing-parent/imdg-hist/src/main/resources/application.properties b/clearing-parent/imdg-hist/src/main/resources/application.properties new file mode 100644 index 000000000..cc380fc77 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/resources/application.properties @@ -0,0 +1,12 @@ +imdg.hist.hazelcast.listenPort=5701 +imdg.hist.hazelcast.login=dev +imdg.hist.hazelcast.password=dev-pass +imdg.hist.hazelcast.cluster-members[0]=127.0.0.1 +imdg.hist.database.login=clearing +imdg.hist.database.password=Aa111111 +imdg.hist.database.url=jdbc:postgresql://10.200.200.133:5432/clearing?currentSchema=clearing_prod +#imdg.database.url=jdbc:postgresql://10.200.200.133:5432/postgres?currentSchema=clearing_tester + +#debug tester mode: +#imdg.debug-server.port=8701 +#imdg.debug-server.context-path=/imdg/reload \ No newline at end of file diff --git a/clearing-parent/imdg-hist/src/main/resources/hazelcast.yaml b/clearing-parent/imdg-hist/src/main/resources/hazelcast.yaml new file mode 100644 index 000000000..d8ca9f792 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/resources/hazelcast.yaml @@ -0,0 +1,5 @@ +hazelcast: + network: + join: + multicast: + enabled: true \ No newline at end of file diff --git a/clearing-parent/imdg-hist/src/main/resources/logback.xml b/clearing-parent/imdg-hist/src/main/resources/logback.xml new file mode 100644 index 000000000..bb03fe824 --- /dev/null +++ b/clearing-parent/imdg-hist/src/main/resources/logback.xml @@ -0,0 +1,38 @@ + + + + + + %date{HH:mm:ss.SSS} [%thread] %-5level %class{0}:%line - %message%n + utf-8 + + + + ./logs/imdg.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %class{0}:%msg%n + utf8 + + + + ./logs/imdg.%i.log + + 1 + 10 + + + 500MB + + + + + + + + + + + + + diff --git a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/base/AutoconfiguredMap1.java b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/base/AutoconfiguredMap1.java new file mode 100644 index 000000000..367e5450d --- /dev/null +++ b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/base/AutoconfiguredMap1.java @@ -0,0 +1,17 @@ +package ru.spcex.clearing.imdg.base; + +import com.hazelcast.core.MapLoader; + +public interface AutoconfiguredMap1 extends MapLoader { + /** + * + * @return IMDGDistributedNames.* + */ + String getMapName(); + + /** + * Список индексируемых полей, для быстрого поиска + * @return + */ + String[] getIndexingField(); +} diff --git a/clearing-parent/pom.xml b/clearing-parent/pom.xml index f67b743ed..b90e0b71c 100644 --- a/clearing-parent/pom.xml +++ b/clearing-parent/pom.xml @@ -41,6 +41,7 @@ swt-exporter swt-importer gateway-api + imdg-hist diff --git a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/clearing/imdg/IMDGDistributedNames.java b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/clearing/imdg/IMDGDistributedNames.java index d4fd82a6b..e5c7cf0a4 100644 --- a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/clearing/imdg/IMDGDistributedNames.java +++ b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/clearing/imdg/IMDGDistributedNames.java @@ -194,6 +194,8 @@ public final class IMDGDistributedNames { public static final String Map_ExecutionFondHistory = "Map_ExecutionFondHistory"; public static final String Map_PriorityDictionary = "Map_PriorityDictionary"; + //-------------------history and search tables + public static final String Map_SearchRegistry = "Map_SearchRegistry"; public static final String MAP_SEQUENCE_NAME = "MAP_SEQUENCE_NAME"; private IMDGDistributedNames() { diff --git a/pom.xml b/pom.xml index e8353b166..758139362 100644 --- a/pom.xml +++ b/pom.xml @@ -84,6 +84,11 @@ imdg ${global.project.version} + + ru.spcex.clearing + imdg-hist + ${global.project.version} + ru.spcex.clearing classes