canvas-lms/gems/dynamic_settings
Cody Cutrer c638e3ada5 bundle update zeitwerk
Change-Id: I21f74bca49f068b1fc9c4c0fbc340aa51cef2956
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/354057
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Isaac Moore <isaac.moore@instructure.com>
Build-Review: Isaac Moore <isaac.moore@instructure.com>
QA-Review: Cody Cutrer <cody@instructure.com>
Product-Review: Cody Cutrer <cody@instructure.com>
2024-08-01 16:49:20 +00:00
..
lib bundle update rubocop 2024-05-30 16:20:52 +00:00
spec handle failsafe caching of consul settings that do not exist 2024-02-21 17:51:43 +00:00
.gitignore handle failsafe caching of consul settings that do not exist 2024-02-21 17:51:43 +00:00
Gemfile bundle update --bundler 2024-04-01 14:22:00 +00:00
Gemfile.lock bundle update zeitwerk 2024-08-01 16:49:20 +00:00
README.md rename Canvas::DynamicSettings => DynamicSettings 2022-01-12 21:54:51 +00:00
dynamic_settings.gemspec rails 7.1: gems/* 2024-02-16 19:46:04 +00:00
test.sh extract dynamic settings to it's own gem 2021-03-01 19:18:01 +00:00

README.md

Dynamic Settings

This is how we load information from Consul for config at runtime. The core idea is that config information is stored in consul as trees. This gem has some opinions about where fallback/override keys will exist for a given config value (region, environment, global) and when you ask for a given key it will search all the places that key might live all the way up to global, return what it finds, and will cache the results for a time in whatever caching implementation you provide to it.

Settings are stored under prefixes in a tree-like structure, and DynamicSettings::find(prefix) lets you query a particular keyspace subtree. Keyspace names used below, such as "Shared Local Configuration".

In local dev, you can use a YAML file as the data source rather than running a Consul server. Start with a cp config/dynamic_settings.yml{.example,} and edit the file from there.

Usage

Fetch the lti-signing-secret config value from the root of the Shared Local Configuration keyspace:

DynamicSettings.find()["lti-signing-secret"]

Fetch the recaptcha_server_key config value from the root of the Private Local Configuration keyspace:

DynamicSettings.find(tree: :private)['recaptcha_server_key']

Create an object to query the live-events configuration keyspace with a long cache TTL and use it to fetch some keys:

le_settings = DynamicSettings.find('live-events', default_ttl: 2.hours)
le_settings['stream_name']
le_settings['acl_token']

Fetch the disable_needs_grading_queries config value, looking first in a keyspace for the activated shard's cluster and, failing that, falling back to local and global keyspaces:

DynamicSettings.find(cluster: Shard.current.database_server.id)["disable_needs_grading_queries"]

Fallback Rules

An initializer configures the DynamicSettings with an environment, e.g. DynamicSettings.config = { 'environment' => 'production' }, which influences the fallback paths followed for any query. The easiest way to describe the behavior is probably through a set of examples, so here we go.

Query: DynamicSettings.find()['key'] Search paths:

config/canvas/production/key
config/canvas/key
global/config/canvas/production/key
global/config/canvas/key

Query: DynamicSettings.find(cluster: 'cluster21')['key'] Search paths:

config/canvas/production/cluster21/key
config/canvas/production/key
config/canvas/key
global/config/canvas/production/key
global/config/canvas/key

Query: DynamicSettings.find(tree: :private, cluster: 'cluster21')['key'] Search paths:

private/canvas/production/cluster21/key
private/canvas/production/key
private/canvas/key
global/private/canvas/production/key
global/private/canvas/key