Skip to main content

How this All Works Together

This section shows a complete configuration and how

  • Your application adds the Superposition Provider as a dependency
  • At runtime, your application will provide a context to the client for evaluation. Using our ride hailing example from earlier, the context provided by your application would look like:
    {
    "city": "Delhi",
    "vehicle_type": "cab",
    "hour_of_day": 19
    }
  • CAC will apply all contexts it has available, and return the final configuration for the application. If no rule applies for a configuration, it's default value will be returned. From our earlier examples (check Default Config and Overrides section) the configuration returned would be
    {
    "per_km_rate": 25.0,
    "surge_factor": 5.0
    }

Analogy with CSS

For people familiar with how CSS works - the following table comparing CAC to CSS will help them grasp CAC's structure quickly

Like CSS, But For Your Backend

Familiar specificity rules for configuration

CSS Cascade

* { color: black; }

.button { color: blue; }

#submit { color: green; }

More specific selector wins

CAC Override

default: surge = 1.0

city=blr: surge = 1.2

city=blr&peak: surge = 1.8

More specific context wins

CSSContext Aware Configuration
body {
  color: black;
}
default {
  color: black
}
#main {
  color: green;
}
[id="main"] {
  color: green
}
.module {
  color: blue;
}
[class="module"] {
  color: blue
}
#main .module {
  color: orange
}
[id="main, class="module"] {
  color: orange
}

The following mapping of concepts between CAC and CSS will also be useful:

CSSContext Aware Configuration
default stylesheetdefault config
propertyconfiguration key
valuevalue (typed)
selectorcontext
(variables involved in contexts are called dimensions)
set of property:valuesoverride
selector + set of property:valuecontextual override

Complete Superposition configuration file in TOML format

The complete context-aware-configuration file for the above example is shown below:

[default-configs]
per_km_rate = { "value" = 20, "schema" = { "type" = "integer" } }
surge_factor = { "value" = 0.0, "schema" = { "type" = "number" } }
ppppp = { schema = { type = "string" }, value = "22" }
test = { schema = { type = "boolean" }, value = false }
untest = { schema = { type = "string", enum = ["s", "a"] }, value = "s" }

[dimensions]
city = { position = 1, schema = { "type" = "string", "enum" = [
"Bangalore",
"Delhi",
] } }
vehicle_type = { position = 2, schema = { "type" = "string", "enum" = [
"auto",
"cab",
"bike",
] } }
hour_of_day = { position = 3, schema = { "type" = "integer", "minimum" = 0, "maximum" = 23 } }
enable_stuff = { position = 4, schema = { "type" = "boolean" } }

[[overrides]]
_context_ = { vehicle_type = "bike", enable_stuff = true }
untest = "s"

[[overrides]]
_context_ = { vehicle_type = "auto" }
per_km_rate = 1

[[overrides]]
_context_ = { vehicle_type = "bike" }
per_km_rate = 15.0

[[overrides]]
_context_ = { city = "Bangalore" }
per_km_rate = 22.0

Interested in writing better config files? Check out SuperTOML