Daemon - Automatically restart on pref changes
Right now, if you change your preferences you must restart the daemon manually. Instead, the Daemon should detect or be told that the preferences have changed and update itself appropriately.
Reload Daemon on pref update
This proposal is the first draft in getting the daemon to refresh the preferences - and thus the config - when a user updates a preference.
I've thought of 2 ways to handle this. Option A and Option B. I've marked each change that is specific to one of the options as such. There are other changes which would be required for both solutions.
Daemon
The daemon will need some extending so we can update the configuration after actually loading the daemon.
(Option A) /internal subroute
The daemon has an AuthProxy which serves the routes for our proxy locally.
Currently, we have a /v1 sub-route which the client uses to communicate with
the daemon.
I'd suggest adding an /internal sub-route where we can add routes for internal
usage, like reloading the config.
/internal/config/reload path
This path would have the daemon as a dependency (we would have to rework how the
proxy actually gets booted as it does not have a reference to the daemon itself),
load the config and call LoadConfig on the daemon.
Upsides vs Downsides
(+) Instant (push based) (-) We need to make the proxy aware of the daemon (to push the config) (-) This will only reload preferences that we set through the API client.
(Option B) Detect filesystem change
We load our preferences from a config file, stored - by default - under
~/.torucrc.
We could have a watcher running to keep checking the configuration file and update the config (and thus the daemon) when we receive a filechange notification.
Upsides vs Downsides
(+) We can detect changes done not through the CLI (-) Delays (pull based, fs notifications are not always instant) (-) How do we handle new errors in the config file?
func LoadConfig
We load our preferences into a Config object, which we pass around to multiple functions and other parts of our system.
This method will load all required dependencies from the config and link them to the daemon.
Dependencies:
- updates (loads preferences on start, no config -> maybe change that?)
- transport (registry uri)
- client (registry uri, transport)
- proxy (client, transport, updates)
We'll call this method from within daemon.New() as well, which will trigger
the initial config setup.
Since these references are all pointers, they should be automatically updated anywhere else we use them.
Note: Definitely want to keep the session in place, this way the user doesn't get logged out.
Locking Middleware
When running a daemon, it's possible to access it concurrently. To avoid config
clashes, I would suggest setting up a Bone Middleware for th /v1 subroutes
with a Read/Write mutex which would always do a RLock. When updating the
config, we would do a regular Lock, which would mean that the Reads would wait
until we've lifted the lock, and thus be done with the new config.
Most of the config actually gets loaded for each command, but some config settings like the registry url are used by the daemon, hence we need to lock this as well.
We could either do this when we do ensureDaemon or when we do a new request.
Client
Depending on where we do the Middleware Locking, we might have to add another change to the client depending on which option we choose for changing the configuration.
Option A
When updating the preferences we also do a call to the new internal path to reload the config.
Note: We first validate if the daemon is running when running this
prefs set command. If it is not, we don't need to do the internal call.
Option B
When choosing Option B, we won't need to change the Client at all because it already updates the config file, which will in its be picked up by the daemon.
Things to figure out:
There's a few things that we should probably figure out by experimenting with some code changes:
- How will the system react when we have proxy (a) running, we update the preferences and set up a new proxy?
- Should we do value change checks? (if
Config.Xchanged, reload dependencyY) - How would we handle filesystem changes on Windows?
Technical questions to be answered:
- [ ] which option do we choose?
- [ ] where do we put the Locking Middleware?