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 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 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