1
0
Fork 0

Add more comments and documentation

This commit is contained in:
Gregory Eremin 2015-08-29 22:36:37 +03:00
parent 604d201c28
commit 46128ee4f6
3 changed files with 18 additions and 12 deletions

View File

@ -64,7 +64,7 @@ secondly.StartServer("", 5500)
Tired of restarting the app every time you modify the config? You're not alone. Tired of restarting the app every time you modify the config? You're not alone.
```go ```go
secondly.HandleFSEvents() secondly.HandleFileSystemEvents()
``` ```
Want some more control over when specifically the config will be reloaded? Ask Want some more control over when specifically the config will be reloaded? Ask

View File

@ -4,8 +4,6 @@ import (
"flag" "flag"
"log" "log"
"github.com/kr/pretty"
"github.com/localhots/secondly" "github.com/localhots/secondly"
) )
@ -44,7 +42,6 @@ func main() {
// Defining callbacks // Defining callbacks
secondly.OnChange("app_name", func(o, n interface{}) { secondly.OnChange("app_name", func(o, n interface{}) {
log.Printf("OMG! AppName changed from %q to %q", o, n) log.Printf("OMG! AppName changed from %q to %q", o, n)
pretty.Println(conf)
}) })
// Other application startup logic // Other application startup logic

View File

@ -1,3 +1,7 @@
// Package secondly is a configuration management plugin for Go projects.
// It takes care of the app's configuration, specifically of updating it in
// runtime. It is capable of listening to file system events and signals to
// trigger configuration reload. It also provides a nice web GUI editor.
package secondly package secondly
import ( import (
@ -24,7 +28,7 @@ var (
initFunc func() initFunc func()
) )
// SetupFlags sets up Confection configuration flags. // SetupFlags sets up Secondly's configuration flags.
func SetupFlags() { func SetupFlags() {
if flag.Parsed() { if flag.Parsed() {
log.Fatalln("secondly.SetupFlags() must be called before flag.Parse()") log.Fatalln("secondly.SetupFlags() must be called before flag.Parse()")
@ -55,16 +59,16 @@ func HandleSIGHUP() {
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGHUP) signal.Notify(ch, syscall.SIGHUP)
go func() { go func() {
for _ = range ch { for range ch {
log.Println("SIGHUP received, reloading config") log.Println("SIGHUP received, reloading config")
readConfig() readConfig()
} }
}() }()
} }
// HandleFSEvents listens to file system events and reloads configuration when // HandleFileSystemEvents listens to file system events and reloads configuration when
// config file is modified. // config file is modified.
func HandleFSEvents() { func HandleFileSystemEvents() {
watcher, err := fsnotify.NewWatcher() watcher, err := fsnotify.NewWatcher()
if err != nil { if err != nil {
panic(err) panic(err)
@ -85,9 +89,6 @@ func HandleFSEvents() {
if e.Name != fname { if e.Name != fname {
continue continue
} }
if !e.IsModify() {
continue
}
log.Println("Config file was modified, reloading") log.Println("Config file was modified, reloading")
readConfig() readConfig()
case err := <-watcher.Error: case err := <-watcher.Error:
@ -104,11 +105,14 @@ func OnLoad(fun func()) {
} }
// OnChange adds a callback function that is triggered every time a value of // OnChange adds a callback function that is triggered every time a value of
// a field changes. // a field changes. Field must be a json tag of the struct field.
func OnChange(field string, fun func(oldVal, newVal interface{})) { func OnChange(field string, fun func(oldVal, newVal interface{})) {
callbacks[field] = append(callbacks[field], fun) callbacks[field] = append(callbacks[field], fun)
} }
// asign is responsible for assigning new config value. It is complicated
// because we're changing the value of an interface which is defined in
// another package.
func assign(target interface{}) { func assign(target interface{}) {
if config == nil { if config == nil {
config = target config = target
@ -120,6 +124,7 @@ func assign(target interface{}) {
cval.Set(tval) cval.Set(tval)
} }
// bootstrap sets up initial configuration.
func bootstrap() { func bootstrap() {
if configFile == "" { if configFile == "" {
log.Fatalln("path to config file is not set") log.Fatalln("path to config file is not set")
@ -207,6 +212,8 @@ func triggerCallbacks(oldConf, newConf interface{}) {
return return
} }
// Secondly accepts only a pointer to stuct as its config value. Here we're
// making sure the right argument is provided.
func isStructPtr(target interface{}) bool { func isStructPtr(target interface{}) bool {
if val := reflect.ValueOf(target); val.Kind() == reflect.Ptr { if val := reflect.ValueOf(target); val.Kind() == reflect.Ptr {
if val = reflect.Indirect(val); val.Kind() == reflect.Struct { if val = reflect.Indirect(val); val.Kind() == reflect.Struct {
@ -217,6 +224,8 @@ func isStructPtr(target interface{}) bool {
return false return false
} }
// duplicate creates a copy of a value behind the config interface. Such copies
// are used to replace config value and to check for changes.
func duplicate(original interface{}) interface{} { func duplicate(original interface{}) interface{} {
// Get the interface value // Get the interface value
val := reflect.ValueOf(original) val := reflect.ValueOf(original)