Uploaded image for project: 'Ignite'
  1. Ignite
  2. IGNITE-13152

Introduce spring-data repository configuration properties

    XMLWordPrintableJSON

Details

    • New Feature
    • Status: Open
    • Major
    • Resolution: Unresolved
    • None
    • None
    • springdata
    • 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:

      1. Create cache by SQL create query.
      2. Add SQL indexes for entity fields.
      3. Set dynamic cache expire policy.
      4. 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) {
              // ...
          }
      }

       

      Attachments

        Activity

          People

            smoldachev Moldachev Sergey
            smoldachev Moldachev Sergey
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: