Details
-
New Feature
-
Status: Open
-
Major
-
Resolution: Unresolved
-
None
-
None
-
None
-
Docs Required, Release Notes Required
Description
Motivation
We have a @RepositoryConfig annotation, which have only one parameter: cacheName (can be simple string or spring evaluate expression). Sometimes we need more flexability, for example:
- Create cache by SQL create query.
- Add SQL indexes for entity fields.
- Set dynamic cache expire policy.
- Set ignite instance bean name, in case when we have a more than one client node (for example we have a separate clusters).
All mentioned above can not be achieved with current @RepositoryConfig. I suggest to introduce the IgniteSpringDataConfiguration bean.
Main idea
The example of ignite-spring-data configuration in yaml format:
ignite-spring-data:
cache-configurations:
SomeEntityCache:
init-sql-script:
- CREATE TABLE IF NOT EXISTS SomeEntity (
name VARCHAR PRIMARY KEY,
executedAt LONG,
executionTime LONG
) WITH "template=replicated,atomicity=atomic,value_type=org.company.SomeEntity,cache_name=SomeEntityCache";
- CREATE INDEX IF NOT EXISTS index_name ON SomeEntity (executedAt);
touchExpirationTimeout: 6_400_000
createExpirationTimeout: 6_400_000
igniteInstanceName: IgniteInstanceBeanName
This configuration can be represent as spring configuration property bean:
@Configuration @ConfigurationProperties(prefix = "ignite-spring-data") public class IgniteSpringDataProperties { /** Map of cache name and configuration. */ private Map<String, RepositoryConfiguration> cacheConfigurations; // getters/setters ommited for readability. public static class RepositoryConfiguration { /** Initial script. */ private List<String> initSqlScript = emptyList(); /** Create expiration timeout. */ private Long createExpirationTimeout; /** Touch expiration timeout. */ private Long touchExpirationTimeout; /** Ignite instance name where cache should be started. */ private String igniteInstanceName = "SomeDefaultIgniteInstanceName"; // Can be null or Optional, place to discusse // getters/setters ommited for readability. } }
This properties we can use in IgniteRepositoryFactory for execute initial sql scripts:
for (Map.Entry<String, GccRepositoryConfiguration> entry : repoProps.getConfigurations().entrySet()) { if (ignite.cache(entry.getKey()) == null) { for (String qryString : entry.getValue().getInitSqlScript()) ignite.context().query().querySqlFields(new SqlFieldsQuery(qryString), true); } }
In IgniteRepositoryFactory#getTargetRepository we can apply expire policy for cache:
IgniteCache<Object, Object> cache = ignite.cache(cacheName); // Apply create expiration timeout. if (cfg.getCreateExpirationTimeout() != null) { ExpiryPolicy plc = CreatedExpiryPolicy.factoryOf(new Duration(MILLISECONDS, cfg.getCreateExpirationTimeout())).create(); cache = cache.withExpiryPolicy(plc); } // Apply touch expiration timeout. if (cfg.getTouchExpirationTimeout() != null) { ExpiryPolicy plc = TouchedExpiryPolicy.factoryOf(new Duration(MILLISECONDS, cfg.getTouchExpirationTimeout())).create(); cache = cache.withExpiryPolicy(plc); } return getTargetRepositoryViaReflection(metadata, cache);
In the IgniteRepositoryFactoryBean#createRepositoryFactory method we can get ignite instance by igniteInstanceName property and create repository factory with specific ignite instance:
/** {@inheritDoc} */ @Override protected RepositoryFactorySupport createRepositoryFactory() { IgniteSpringDataProperties springDataProps = ctx.getBean(IgniteSpringDataProperties.class); try { String cacheName = getObjectType().getAnnotation(RepositoryConfig.class).cacheName(); RepositoryConfiguration cfg = springDataProps.configuration(cacheName); IgniteEx ignite = (IgniteEx)ctx.getBean(cfg.getIgniteInstanceName()); return new IgniteRepositoryFactory(ignite, repoProps); } catch (BeansException ex) { // ... } }