gekomad / hot-reload   1.1.0

Apache License 2.0 GitHub

Dynamic configuration library for Scala

Scala versions: 2.13 2.12 2.11

Hot-Reload Build Status codecov Javadocs Maven Central

Hot-reload is a static/dynamic configurator based on Config.

Add the library to your project

libraryDependencies += "com.github.gekomad" %% "hot-reload" % "1.1.0"

Motivations

Generally, in a software project the majority of configuration files are static. This means that, to modify the parameters, the application must be deployed anew. Although most parameters must not change as long as the application is live, others might change, even temporarily.

Hot-reload allows you to manage unmodifiable and modifiable configuration files.

Using Library

There are two modes: mutable and immutable. The first one creates a configurator that modifies the parameters when the original conf file is modified. The second one allows you to create a configurator that does not change when the original conf file is modified. Two (or more) configuration files could be created (one for the parameters that can change and the other for the immutable parameters) and given to the application in this manner.

./my_app -Dmutable_conf=/path/mutable.conf -Dimmutable_conf=/path/immutable.conf

Examples

First of all some definitions
 case class FooConfig(bar: String, baz: Option[Int], list: List[Int], missingValue: Option[String])  

file /path/conf1.conf:

{  
   bar = "conf_1",  
   baz = 1,  
   list = [1, 1, 111]  
}  

file /path/conf2.conf:

{  
   bar = "conf_2",  
   baz = 2,  
   list = [2, 2, 222]  
}  

file /path/confErr.conf:

{  
   bar = 1, // this is an error, bar must be a String  
   baz = 42,  
   list = [1, 2, 3]  
}  

Create a mutable config

import com.github.gekomad.hotreload.core.HotReload  
copyFile(from = "/path/conf1.conf", to = "/path/mutable.conf")  

//create HotReload from conf1.conf file  
val hr: Try[HotReload[FooConfig]] = HotReload[FooConfig]("/path/mutable.conf", mutable = true)

hr match {  
  case Success(hotReload) => {  
  
    {  // hotReload contains conf1  
     assert(hotReload.currentConf == FooConfig("conf_1", Some(1), List(1, 11, 111), None))
    }  
  
    {  
     Thread.sleep(1000)  
     copyFile(from = "/path/conf2.conf", to = "/path/mutable.conf")  
     Thread.sleep(1000)  
     assert(hotReload.currentConf == FooConfig("conf_2", Some(2), List(2, 22, 222), None))  
     // now hotReload contains conf2
    }  
  
    {     
     copyFile(from = "/path/confErr.conf", to = "/path/mutable.conf")  
     Thread.sleep(1000)  
     assert(hotReload.currentConf == FooConfig("conf_2", Some(2), List(2, 22, 222), None))  
     // hotReload still contains conf2 because confErr.conf file is wrong
    }  
  }
  case Failure(f) => println(s"error on loading file ${f.getMessage}")
}  

Create an immutable config

import com.github.gekomad.hotreload.core.HotReload  
    
copyFile(from = "/path/conf1.conf", to = "/path/immutable.conf")  
  
//create HotReload from conf1 file, set 'mutable = false' to make it immutable  
val hr: Try[HotReload[FooConfig]] = HotReload[FooConfig]("/path/immutable.conf", mutable = false)  
hr match {  
  case Success(hotReload) =>  
  
    // hotReload contains conf1  
    assert(hotReload.currentConf == FooConfig("conf_1", Some(1), List(1, 11, 111), None))  
  
    // modifying conf file, hotReload still contains conf1 because it's immutable
    copyFile(from = "/path/conf2.conf", to = "/path/immutable.conf")  
    Thread.sleep(1000)  
  
    assert(hotReload.currentConf == FooConfig("conf_1", Some(1), List(1, 11, 111), None))

  case Failure(f) => println(s"error on loading file ${f.getMessage}")
}  

Bugs and Feedback

For bugs, questions and discussions please use Github Issues.

License

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.

Special Thanks

To lambdista for his library.