Loading…
Loading…
Describes the caching repository for runtime system settings, which uses a time-to-live (TTL) cache to reduce database load during request processing.
The RuntimeSettingRepository is a component responsible for reading operator-configurable system settings from the s2r_system_setting database table. Its primary purpose is to improve performance and reduce database load under high request volumes.
During the processing of a single API request, the runtime may need to resolve 15-20 different system settings. Querying the database for each setting on every request can create a significant performance bottleneck, leading to thousands of extra queries per second at high traffic rates.
To solve this, RuntimeSettingRepository implements a hot-path, time-to-live (TTL) cache. It stores a local, in-memory snapshot of settings, drastically reducing database round-trips. This component provides low-precedence default values to other parts of the request-processing pipeline, such as the ConversionOptionResolver. Per-operation overrides, which are loaded with a route, still take precedence over the system defaults provided by this repository.
The repository caches the raw JSON text of a setting's value, not the parsed result. This allows for a flexible and efficient caching strategy that supports various data types. The caching mechanism is designed to be resilient, thread-safe, and aware of multi-tenant environments.
flowchart TD
subgraph "Setting Accessor"
A[Call for setting 'key']
end
A --> B{Value in cache for 'key'?}
B -- "Yes, and not expired" --> C[Return cached value]
subgraph "Cache Refresh"
B -- "No, or expired" --> D[Query database for setting]
D -- Success --> E[Update cache with new value and TTL]
E --> C
D -- "DB Error" --> F{Stale value in cache?}
F -- "Yes" --> G[Serve stale value]
G --> H[Extend stale value's TTL]
H --> I[Log WARN]
I --> C
F -- "No" --> J[Throw exception]
J --> K[Log WARN]
subgraph "Special Case: Unbound Tenant"
D -- "DB Error (S2R-TENANCY-UNBOUND)" --> L[Throw exception]
L --> M[Remove key from cache]
M --> N[Log WARN]
end
endSettings are cached for a configurable duration, known as the Time-To-Live (TTL).
S2R_RUNTIME_SETTING_CACHE_TTL_SECONDS environment variable.The cache is designed for multi-tenant deployments and ensures that one tenant cannot access another's settings.
(tenantId, settingKey).unbound scope. This prevents it from being served a cached value belonging to the default tenant, forcing a database check which may be gated by security policies.The cache is implemented using a ConcurrentHashMap of immutable Snapshot records, ensuring high performance in multi-threaded environments.
The repository is designed to be resilient to transient database failures.
WARN level message is logged.WARNING
Unbound Tenant Exception
The fail-safe behavior does not apply to errors indicating a request has no tenant context (S2R-TENANCY-UNBOUND). In this scenario, the exception is always re-thrown to the caller, and any existing cache entry for that key is evicted. This is a security measure to prevent unauthenticated callers from accessing settings.
The cache's behavior can be tuned with the following environment variable.
| Name | Type | Default | Description |
|---|---|---|---|
S2R_RUNTIME_SETTING_CACHE_TTL_SECONDS | long | 60 | The time-to-live (TTL) in seconds for cached system settings. After this period, the setting is refreshed from the database on its next access. The minimum effective value is 1. |
The RuntimeSettingRepository exposes several public accessor methods for retrieving settings of different types. These methods handle the logic of checking the cache, querying the database, and parsing the raw value.
getJsonStringListReads a field from a JSON object stored as a setting. The field's value is expected to be a JSON array of strings.
public List<String> getJsonStringList(String key, String field)
key: The setting_key of the system setting.field: The name of the field within the JSON object to read.List<String> containing the elements of the JSON array. Returns null if the setting does not exist, the field is missing, or the value is not a JSON array.To retrieve a denylist of headers from a setting named conversion_defaults_header_propagation:
// Assuming the setting value is: {"headerDenylist": ["Security", "Authorization"]}
List<String> denylist = getJsonStringList("conversion_defaults_header_propagation", "headerDenylist");
// denylist will contain ["Security", "Authorization"]
getJsonStringFieldReads a field from a JSON object stored as a setting and returns its string representation.
public String getJsonStringField(String key, String field, String defaultValue)
key: The setting_key of the system setting.field: The name of the field within the JSON object to read.defaultValue: The value to return if the setting or field is not found.defaultValue if the setting, field, or value is missing or null.getIntReads a setting whose value is a single integer.
public int getInt(String key, int defaultValue)
key: The setting_key of the system setting.defaultValue: The value to return if the setting is not found or its value cannot be parsed as an integer.int value of the setting or defaultValue.getLongReads a setting whose value is a single long integer.
public long getLong(String key, long defaultValue)
key: The setting_key of the system setting.defaultValue: The value to return if the setting is not found or its value cannot be parsed as a long.long value of the setting or defaultValue. If parsing fails, a WARN message is logged.getBooleanReads a setting whose value is a single boolean.
public boolean getBoolean(String key, boolean defaultValue)
key: The setting_key of the system setting.defaultValue: The value to return if the setting is not found or its value is not a recognized boolean.boolean value of the setting. The strings "true" (case-insensitive) and "1" are interpreted as true. All other values are false.| Condition | Trigger | Behavior |
|---|---|---|
| Database refresh fails | A transient database error occurs during a cache refresh. | If a stale value is present in the cache, it is served and its TTL is extended. A WARN message is logged. If no value is cached, the database exception is propagated to the caller. |
| Read attempt without tenant context | An API call is processed in a multi-tenant environment without a valid tenant context being bound. | A security gate rejects the database read, causing an S2R-TENANCY-UNBOUND error. This exception is always thrown to the caller. Any cached value for the requested key is evicted. A WARN message is logged. |
Unparseable long value | The value for a setting read via getLong is not a valid long integer (e.g., "abc"). | The defaultValue is returned. A WARN message is logged, including the setting key and the unparseable value. |
Unparseable int or boolean value | The value for a setting read via getInt or getBoolean is not valid for its type. | The defaultValue is returned silently. No warning is logged. |
| Invalid JSON structure | The value for a setting read via getJsonStringList or getJsonStringField is not a valid JSON object. | The method returns null or the defaultValue, respectively. No warning is logged. |
ConversionOptionResolver: A primary consumer of the settings provided by this repository, which uses them to resolve final behavior for request processing.RuntimeRouteCacheService: A component that manages caching for routing information, using a similar tenant-scoped, TTL-based caching pattern.PayloadLimitFilter: Another component in the platform that employs a similar refresh-cache idiom for its configuration.