Storing Config in DB¶
We’re getting ahead of ourselves a little here, if you’re reading this manual straight through. But for reference sake this probably belongs here.
Settings Table¶
If you already have a Rattail DB, then it has a table named setting
which
is designed to store config values. It’s just a regular table so you can write
settings via SQL if you like:
insert into setting (name, value) values ('rattail.app_title', 'Poser');
update setting set value = 'Something Else' where name = 'rattail.app_title';
Although the main reason for putting settings in the DB is usually so you can edit them via the web app.
Telling App to Read Config from DB¶
Well first of all we must assume that the DB connection itself is configured. More on that later but let’s say you have this in place:
[rattail.db]
default.url = postgresql://user:password@localhost/poser
Then you also must tell the Rattail config engine that a) it should read config values from the DB at all, but probably also b) it should prefer values from the DB over what was read from file. Do this within your config file:
[rattail.config]
usedb = true
preferdb = true
With this in place, when the app requests a config value, it will come from the DB if present, falling back to the file value if that exists.
File vs. DB Setting Names¶
You may have noticed that the SQL examples above, and the examples
used in Config File Syntax are really for the same app_title
setting,
but there is a key difference in naming.
So in a config file you might have this snippet to define a setting:
[rattail]
app_title = Poser
But then that same setting is written in SQL as:
insert into setting (name, value) values ('rattail.app_title', 'Poser');
In other words the “section” and “option” names from the config file, are joined together with a dot, for the DB setting name.
When the app requests a config value, it must specify both a section and option. The config engine then will auto-join them as needed when doing DB lookups.
config.get('rattail', 'app_title')
Avoiding the DB¶
The app can request config from “file only” if it needs to. It just has to specify a flag when reading the value, for example:
config.get('rattail', 'app_title', usedb=False)
DB Settings Cache¶
Warning
Unfortunately at this time the caching mechanisms described below are not reliable. Docs remain in place for now, but it is very much not recommended to enable caching.
One downside of reading config values from the DB settings table, is
the number of queries involved, as each call to config.get()
would
normally involve a separate SQL query. (Not only that, but unless a
DB session is passed to config.get()
a new one will be made just
for the query.)
To help with this, you can enable caching for the DB settings. This
should “just work” as expected; i.e. calls to config.get()
need
not change. (Although there’s no point in passing a DB session when
caching is enabled.)
To turn on the caching, add to your config file:
[rattail.config]
beaker_cache.enabled = true
By default this cache will be file-based, storage for which is at
e.g. /srv/envs/poser/app/cache/config/
although you can override
the paths if you prefer:
[rattail.config]
beaker_cache.enabled = true
beaker_cache.data_dir = /somewhere/else/data
beaker_cache.lock_dir = /somewhere/else/lock
Note that by default there is no expiration for the cache values, meaning once a particular setting is cached, that value will never expire, and therefore the setting will never be re-fetched from DB (unless a new value is written for it, in which case the cache is invalidated for that setting, which causes a re-fetch next time it’s requested). You may want values to expire after say, an hour, so that settings will periodically be re-fetched regardless of write activity. Do that by specifying the number of seconds after which values should expire:
[rattail.config]
# nb. expire values after 1 hour
beaker_cache.expire = 3600
memcached¶
If you’re not crazy about caching to disk and would prefer to use memcached as the backend instead, first install that:
sudo apt install memcached
Then install the Python dependencies to your virtual environment:
cd /srv/envs/poser
source bin/activate
pip install 'rattail[memcached]'
And finally add to your config file:
[rattail.config]
beaker_cache.enabled = true
beaker_cache.type = ext:memcached
beaker_cache.url = 127.0.0.1:11211
Rattail will try to come up with a unique namespace to use for the
cache; this is needed in situations where the same memcached
service is handling multiple “separate” Rattail apps. You can also
explicitly set the namespace to use, e.g.:
[rattail.config]
beaker_cache.namespace = my_custom_namespace