Skip to content

contek-io/io.contek.tinker

Repository files navigation

io.contek.tinker

A Java library to automatically reload and cache configs.

Maven

<dependency>
    <groupId>io.contek.tinker</groupId>
    <artifactId>tinker-reloading-store</artifactId>
    <version>2.2.1</version>
</dependency>

<dependency>
    <groupId>io.contek.tinker</groupId>
    <artifactId>tinker-reloading-store-yaml</artifactId>
    <version>2.2.1</version>
</dependency>

Example

  1. Declare Yaml config file structure
     /**
      * Yaml file structure. Good practices:
      * <li>Snake cases
      * <li>Public field
      * <li>No constructor
      * <li>No method
      * <li>Use primitives only
      * <li>Specify unit in field name
      */
      public final class YamlFile {
          public int int_value;
          public String string_value;
          public int duration_in_seconds;
      }
  2. Create parsed config POJO class
    /**
     * Parsed config file. Good practices:
     * <li>Camel cases (like normal java code)
     * <li>Private fields
     * <li>Strictly immutable
     * <li>Get methods only
     * <li>Use sophisticated classes (Enum, Instant, Duration etc)
     */
    public final class MyParsedConfig {
        private final int intValue;
        private final String stringValue;
        private final Duration durationValue;
        
        public MyParsedConfig(int intValue, String stringValue, Duration durationValue) {
            this.intValue = intValue;
            this.stringValue = stringValue;
            this.durationValue = durationValue;
        }
        
        public int getIntValue() {
            return intValue;
        }
        
        public String getStringValue() {
            return stringValue;
        }
        
        public Duration getDurationValue() {
            return durationValue;
        }
    }
  3. Create parser
    /**
     * Parser to create parsed config from Yaml file. Good practices:
     * <li>Stateless
     */
    public final class Parser extends YamlParser<YamlFile, MyParsedConfig> {
    
        @Override
        protected Class<YamlFile> getYamlType() {
            return YamlFile.class;
        }
    
        @Override
        protected MyParsedConfig parse(Path path, YamlFile yaml) {
            return new MyParsedConfig(yaml.int_value, yaml.string_value, durationValue);
        }
    }
  4. Create store
    /**
     * Store to cache parsed config. Good practices:
     * <li>No field
     * <li>Log on state change
     * <li>No set method
     */
    public final class ReamStoreExample extends ReloadingStore<MyParsedConfig>
        implements ReloadingStore.IListener<MyParsedConfig> {
    
        public ReamStoreExample(Path configPath) {
            super(configPath, new Parser());
            addListener(this);
            start();
        }
    
        @Nullable
        public Instant getExpiry() {
            MyParsedConfig config = getParsedConfig();
            if (config == null) {
                return null;
            }
            return Instant.now().plus(config.getDurationValue());
        }
    
        @Override
        public void onError(Throwable t) {
            t.printStackTrace();
        }
    
        @Override
        public void onReload(
                Path path,
                MyParsedConfig newValue,
                @Nullable MyParsedConfig oldValue,
                Instant modifiedTime) {
            System.out.println("New int value is " + newValue.getIntValue());
            System.out.println("New string value is " + newValue.getStringValue());
        }
    }
  5. Use the store
    /**
    * An example that uses ReamStoreExample. Good practices:
    * <li>Handle null case properly 
    */
    public class Example {
        private final ReamStoreExample store;
        private final BlockingQueue<Instant> queue;
        
        public Example(ReamStoreExample store, BlockingQueue<Instant> queue) {
            this.store = store;
            this.queue = queue;
        }
    
        public void checkNextAgainstExpiry() throws InterruptedException {
            Instant expiry = store.getExpiry();
            if (expiry == null) {
                System.out.println("No expiry information");
                return;
            }
            Instant next = queue.take();
            if (next.isBefore(expiry)) {
                System.out.println(next + " is OK");
            } else {
                System.err.println(next + " is outdated");
            }
        }
    }

Additional templates

This library also provides other types of store templates to help you with configs which use common data types:

  • ReloadingBiMapStore and YamlBiMapParser
  • ReloadingListStore and YamlListParser
  • ReloadingMapStore and YamlMapParser
  • ReloadingMultimapStore and YamlMultimapParser
  • ReloadingSetStore and YamlSetParser
  • ReloadingTableStore and YamlTableParser

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages