dominictarr / rc

The non-configurable configuration loader for lazy people.
Other
1.02k stars 97 forks source link

Is there a way to reload config dynamically while running? #45

Closed megastef closed 9 years ago

megastef commented 9 years ago

I'm looking for a way to change e.g. debug level in config and apply this during runtime. Is thre any support of watching config file and trigger event on config change / or directly apply values?

dominictarr commented 9 years ago

Hi, can you provide a more detailed description of your system, and how it uses configuration? You should also describe what it is that your application is for, because context is very helpful.

This does sound like it may be useful, but I am not sure whether this should be exposed in rc by default. This may work well as another module that uses parts from rc (some refactoring may be involved)

I'd imagine in many cases when the configuration changes you would probably just restart the application? hmm, but other cases, like, logging levels could just be applied directly (your app could just read the config.loglevel at each call to log so it wouldn't even need to process an event...

megastef commented 9 years ago

Hi, we use "rc" in the Node.js client for a performance monitoring solution. https://github.com/sematext/spm-agent-nodejs The typical instruction to users would be to change the configuration files and restart the monitored service just to a get a detailed log. After a problem is recognized and fixed, the log might be switched off again. Just one example, many use cases (e.g. switch monitoring features on/off)

There are two issues: 1) Updating the configuration from changed file (which I think belongs here) My initial thought was to build it in our package. But in next project I would need to do this again, or wrap something around rc - e.g. in our utility functions. Thats why I ask here: dynamic configuration reload seems to be a common feature, and might exists already ...

2) Make the own application aware about dynamic config changes

dominictarr commented 9 years ago

@megastef thanks. so I think the main part of this is a thing that watches the places where rc would load files from. I'm not sure whether I'd want to make this part of core rc (just because it's not needed most of the time and could compilexifcate the interface), but it sounds like it would be great as a separate module (if it was compatible with the way rc loads config I would link it is the readme).

So, you'd want to use code from rc that actually figures out where to look for files, that part may need to be refactored, and exposed in rc so that the watcher can look in the same places.

Would you be interested in making a pull request?

megastef commented 9 years ago

Would it be sufficient to watch just 'rc.config' filename, or all in rec.configs array ? See structure of the rc object below:

> rc = require ('rc')('spmagent')
{ dbDir: './spmdb',
  tokens: { spm: 'XXX-XXX-XXX', '': true },
  logger: { dir: './spmlogs', silent: false, level: 'error' },
  _: [],
  configs: [ '/Users/stefan/sematext/njs-packages/.spmagentrc' ],
  config: '/Users/stefan/sematext/njs-packages/.spmagentrc' }
}

In that case I would suggest a separate package (like rc-file-watcher) maybe using https://www.npmjs.com/package/file-watch

kessler commented 9 years ago

Just a small caveat from my personal experience with dynamic reloading, once you do that you must make sure that all references to config data always go through the config object. No closures or local variables are allowed:

var config = require('./config')
var thing = config.thing

module.exports = function foo() {
    return thing
}

Dynamically reloading the config at this point won't change the value of thing returned by the exported function. I can describe a few other scenarios like this but I trust you get the picture.

dominictarr commented 9 years ago

@kessler good point.

@megastef really, it should watch all the places that it might load config from, because if you moved a file from ~.apprc to ~.app/config, and restarted the application then it would load that file, I wouldn't want to have behavior that could be different between reloading and restarting.

you'd basically just have to move this code into another js file that returned an array of all the config possibly config files https://github.com/dominictarr/rc/blob/master/index.js#L36-L46

megastef commented 9 years ago

Thx for all the information. I came to the conclusion that reloading triggers are application specific. For example handling process signals instead of watching many files. To load new values, simply the rc object needs to be replaced with a new instance. All functions using this object might need to get an event to be able to update internal values if they are derived from config values. I think we can close the issue in rc, and maybe have another package as wrapper around rc to provide common functions (e.g. handling signal, recreate object, send event). I hope I can get to this in the next weeks.

dominictarr commented 9 years ago

good plan.