This commit is contained in:
parent
1c9de78f5e
commit
fae7a37424
26 changed files with 943 additions and 0 deletions
173
clearing-parent/imdg-hist/pom.xml
Normal file
173
clearing-parent/imdg-hist/pom.xml
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>clearing-parent</artifactId>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<version>SPCEX-1.0.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>imdg-hist</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<artifactId>imdg</artifactId>
|
||||
<version>SPCEX-1.0.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<artifactId>classes</artifactId>
|
||||
<version>SPCEX-1.0.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<artifactId>dictionary</artifactId>
|
||||
<version>SPCEX-1.0.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JDBC -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- IMDG для MapStore -->
|
||||
<dependency>
|
||||
<groupId>com.hazelcast</groupId>
|
||||
<artifactId>hazelcast-all</artifactId>
|
||||
<version>${external_libraries.hazelcast.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-imdg-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-imdg-api-hazelcast-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-enum</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<artifactId>cleaning-builders</artifactId>
|
||||
<version>SPCEX-1.0.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<artifactId>clearing-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.skyscreamer</groupId>
|
||||
<artifactId>jsonassert</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>application.properties</exclude>
|
||||
</excludes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>ru.spcex.clearing.historyimdg.IMDGHistApplication</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<addResources>true</addResources>
|
||||
<classifier>exec</classifier>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.21.0</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-surefire-provider</artifactId>
|
||||
<version>1.2.0-M1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.2.0-M1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MapConfig> autoMapCfg = poolMapConfigs.configureEachMapStore();
|
||||
for (MapConfig cfg : autoMapCfg) {
|
||||
config.addMapConfig(cfg);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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<AutoconfiguredMap1<?>> autoconfiguredMaps;
|
||||
|
||||
@Autowired
|
||||
public HistoryPoolMapConfigs(List<AutoconfiguredMap1<?>> autoconfiguredMaps) {
|
||||
this.autoconfiguredMaps = autoconfiguredMaps;
|
||||
}
|
||||
|
||||
private MapStoreConfig makeDefaultMapStoreConfig(MapLoader<Long, ?> mapBean) {
|
||||
return new MapStoreConfig()
|
||||
.setImplementation(mapBean);
|
||||
}
|
||||
|
||||
|
||||
public MapConfig makeDefaultMapConfig(String mapName, MapLoader<Long, ?> 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<MapConfig> configureEachMapStore() {
|
||||
List<MapConfig> out = new ArrayList<>();
|
||||
HashSet<String> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String> 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<String> getClusterMembers() {
|
||||
return clusterMembers;
|
||||
}
|
||||
|
||||
public void setClusterMembers(List<String> clusterMembers) {
|
||||
this.clusterMembers = clusterMembers;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package ru.spcex.clearing.historyimdg.index.field;
|
||||
|
||||
public interface SearchCompanyId {
|
||||
Long getCompanyId();
|
||||
|
||||
void setCompanyId(Long id);
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package ru.spcex.clearing.historyimdg.index.field;
|
||||
|
||||
public interface SearchWithId {
|
||||
Long getId();
|
||||
|
||||
void setId(Long id);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package ru.spcex.clearing.historyimdg.index.field;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public interface SearchWithTradingDay {
|
||||
LocalDate getTradingDate();
|
||||
|
||||
void setTradingDate(LocalDate tradingDate);
|
||||
}
|
||||
|
|
@ -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<T extends WithId> implements AutoconfiguredMap<T> {
|
||||
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<T> rows;
|
||||
List<Long> 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<Long, T> loadAll(Collection<Long> keys) {
|
||||
log.debug("loadAll from " + getTableName() + " " + keys.size() + " keys");
|
||||
Map<Long, T> result = new HashMap<>();
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
// загрузить данные по ключам частями, чтобы не выйти за ограничения базы по кол-ву элементов в in clause
|
||||
List<Long> keysSubList = new ArrayList<>(MAX_IN_CLAUSE_SIZE);
|
||||
for (Iterator<Long> iterator = keys.iterator(); iterator.hasNext(); ) {
|
||||
Long key = iterator.next();
|
||||
keysSubList.add(key);
|
||||
if (keysSubList.size() == MAX_IN_CLAUSE_SIZE || !iterator.hasNext()) {
|
||||
Collection<T> 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<Long> loadAllKeys() {
|
||||
log.debug("loading all keys from {}...", getTableName());
|
||||
Instant yesterdayInstant = Instant.now().minus(0, ChronoUnit.DAYS);
|
||||
Instant halfYearAgo = yesterdayInstant.minus(365, ChronoUnit.DAYS);
|
||||
List<Long> 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<T> load(Collection<Long> keys);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package ru.spcex.clearing.historyimdg.mapstores;
|
||||
|
||||
public interface HistMapStore {
|
||||
}
|
||||
|
|
@ -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<Long> loadAllKeys() {
|
||||
// log.debug("RegistryHistoryMapStore loadAllKeys is called");
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// @Bean
|
||||
// public AutoconfiguredMap<?> registrySomeMapStore(Class<? extends AutoconfiguredMap<?>> 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<Long> loadAllKeys() {
|
||||
// log.debug("RegistryHistoryMapStore loadAllKeys is called");
|
||||
// return new ArrayList<>();
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
}
|
||||
|
|
@ -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<Long> loadAllKeys() {
|
||||
log.debug("RegistryHistoryMapStore loadAllKeys is called");
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
|
@ -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<SearchProxyRegistry> {
|
||||
public SearchRegistryMapStore(JdbcTemplate jdbcTemplate) {
|
||||
super(jdbcTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTableName() {
|
||||
return "registry";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SearchProxyRegistry> load(Collection<Long> keys) {
|
||||
Map<String, Collection<Long>> 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"};
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
hazelcast:
|
||||
network:
|
||||
join:
|
||||
multicast:
|
||||
enabled: true
|
||||
38
clearing-parent/imdg-hist/src/main/resources/logback.xml
Normal file
38
clearing-parent/imdg-hist/src/main/resources/logback.xml
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<!-- |%X{ru.nbch.scoring.web.logging.mdc_key}-->
|
||||
<Pattern>%date{HH:mm:ss.SSS} [%thread] %-5level %class{0}:%line - %message%n</Pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>./logs/imdg.log</file>
|
||||
<encoder>
|
||||
<!-- |%X{ru.nbch.scoring.web.logging.mdc_key}-->
|
||||
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %class{0}:%msg%n</Pattern>
|
||||
<charset>utf8</charset>
|
||||
</encoder>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
|
||||
<fileNamePattern>
|
||||
./logs/imdg.%i.log
|
||||
</fileNamePattern>
|
||||
<minIndex>1</minIndex>
|
||||
<maxIndex>10</maxIndex>
|
||||
</rollingPolicy>
|
||||
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||
<maxFileSize>500MB</maxFileSize>
|
||||
</triggeringPolicy>
|
||||
</appender>
|
||||
|
||||
<root level="warn">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
|
||||
<logger name="ru.spcex" level="debug" additivity="false">
|
||||
<appender-ref ref="FILE"/>
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
</configuration>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package ru.spcex.clearing.imdg.base;
|
||||
|
||||
import com.hazelcast.core.MapLoader;
|
||||
|
||||
public interface AutoconfiguredMap1<T> extends MapLoader<Long, T> {
|
||||
/**
|
||||
*
|
||||
* @return IMDGDistributedNames.*
|
||||
*/
|
||||
String getMapName();
|
||||
|
||||
/**
|
||||
* Список индексируемых полей, для быстрого поиска
|
||||
* @return
|
||||
*/
|
||||
String[] getIndexingField();
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@
|
|||
<module>swt-exporter</module>
|
||||
<module>swt-importer</module>
|
||||
<module>gateway-api</module>
|
||||
<module>imdg-hist</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
5
pom.xml
5
pom.xml
|
|
@ -84,6 +84,11 @@
|
|||
<artifactId>imdg</artifactId>
|
||||
<version>${global.project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<artifactId>imdg-hist</artifactId>
|
||||
<version>${global.project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.clearing</groupId>
|
||||
<artifactId>classes</artifactId>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue