We load configuration data once from zookeeper and conceal it in a name space.
Changing the context is quite simple, we reload resources in this name space
using a minimal list of properties which says where the configuration data should be
pulled from in zookeeper.
This is doable from the REPL at any time. No other name space keeps
this stuff in vars. Any external resource is pulled at runtime from the
configuration name space where they are cached except for some very short lived
structures (requests to storage, locks, queues, channels, ... for the duration of
the request).
Test configuration data is also contained in zookeeper. Tests
pull from this configuration tree the configuration they need.
Part of the test stubbing is kept in this configuration.
No mutations occur in the configuration data from zookeeper during the "normal"
app life cycle. We allow config changes while the app is running but in a special
context of its life cycle. Namely the app has to enter a state that allows it to
reconfigured itself. This means that workers have been stopped, ....
We can test a new configuration without mutating the previous one in zookeeper
using a versioning scheme.
This requires some discipline enforced by the configuration name space API.
So far it's been a charm to work with.
Luc P.
> > - Pass the configs map along with each Ring request with some
> > middleware, and then down every subsequent function call that might
> > eventually need it. It's a bit of a hassle since now you're passing more
> > data, potentially increasing the # of parameters, or forcing you to use a
> > parameter map everywhere where you might have passed along just 1
> > primitive. Nonetheless, this is as pure as it gets.
> > - Def the configs map in a namespace somewhere and refer to it from
> > wherever, just like global state. The trick is now that now you're no
> > longer certain what e.g. your model functions are expecting there to be in
> > the system and testing becomes trickier. Now you have to either lein test
> > with a separate set of configurations (which doesn't actually give you much
> > per-test granularity) or use with-redefs everywhere to make sure the right
> > test config state is being used.
> > - Something in the middle where perhaps you agree to never directly
> > reference the configs map from your models (again, thinking MVC here) and
> > instead only ever access it from controllers, and pass the necessary
> > options along down to the model functions. This way you can test both
> > controllers and models in isolation in purity.
> >
> > Ultimately I want to contain the chaos of having to know internal
> > implementation details of my functions at different layers and want them to
> > be easily testable in isolation. It does seem like the first option is the
> > most straightforward, but I'd be curious to find out what those of you who
> > have deal with the problem for a while would recommend. Purity all the way,
> > or are there patterns that can give you the best of both worlds? Or what
> > else?
> >
> >
> >
>