Load cache factors from the environment, and add a test.

anoa/temp_working_cache_config
Amber H. Brown 2020-01-21 23:46:08 +11:00
parent 0b069b70a1
commit a96b5d9ca7
2 changed files with 78 additions and 27 deletions

View File

@ -17,15 +17,11 @@ import os
from collections import defaultdict
from typing import DefaultDict
from twisted.logger import Logger
from ._base import Config, ConfigError
log = Logger()
_CACHES = {}
DEFAULT_CACHE_SIZE_FACTOR = float(os.environ.get("SYNAPSE_CACHE_FACTOR", 0.5))
_CACHE_PREFIX = "SYNAPSE_CACHE_FACTOR"
DEFAULT_CACHE_SIZE_FACTOR = float(os.environ.get(_CACHE_PREFIX, 0.5))
_DEFAULT_CONFIG = """\
# Cache configuration
@ -51,6 +47,7 @@ def add_resizable_cache(cache_name, cache_resize_callback):
class CacheConfig(Config):
section = "caches"
_environ = os.environ
def read_config(self, config, **kwargs):
self.event_cache_size = self.parse_size(config.get("event_cache_size", "10K"))
@ -68,10 +65,20 @@ class CacheConfig(Config):
# Set the global one so that it's reflected in new caches
DEFAULT_CACHE_SIZE_FACTOR = self.global_factor
individual_factors = cache_config.get("per_cache_factors", {}) or {}
if not isinstance(individual_factors, dict):
# Load cache factors from the environment, but override them with the
# ones in the config file if they exist
individual_factors = {
key[len(_CACHE_PREFIX) + 1 :].lower(): float(val)
for key, val in self._environ.items()
if key.startswith(_CACHE_PREFIX + "_")
}
individual_factors_config = cache_config.get("per_cache_factors", {}) or {}
if not isinstance(individual_factors_config, dict):
raise ConfigError("caches.per_cache_factors must be a dictionary")
individual_factors.update(individual_factors_config)
self.cache_factors = defaultdict(
lambda: self.global_factor
) # type: DefaultDict[str, float]
@ -82,22 +89,3 @@ class CacheConfig(Config):
"caches.per_cache_factors.%s must be a number" % (cache.lower(),)
)
self.cache_factors[cache.lower()] = factor
def resize_caches(self):
for cache_name, cache_resize_callback in _CACHES.items():
cache_factor = self.cache_factors[cache_name]
log.debug(
"Setting cache factor for {cache_name} to {new_cache_factor}",
cache_name=cache_name,
new_cache_factor=cache_factor,
)
changed = cache_resize_callback(cache_factor)
if changed:
log.info(
"Cache factor for {cache_name} set to {new_cache_factor}",
cache_name=cache_name,
new_cache_factor=cache_factor,
)
def get_factor_for(self, cache_name):
return self.cache_factors[cache_name.lower()]

View File

@ -0,0 +1,63 @@
# -*- coding: utf-8 -*-
# Copyright 2020 Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from synapse.config._base import Config, RootConfig
from synapse.config.cache import CacheConfig
from tests.unittest import TestCase
class FakeServer(Config):
section = "server"
class TestConfig(RootConfig):
config_classes = [FakeServer, CacheConfig]
class CacheConfigTests(TestCase):
def test_individual_caches_from_environ(self):
"""
Individual cache factors will be loaded from the environment.
"""
config = {}
t = TestConfig()
t.caches._environ = {
"SYNAPSE_CACHE_FACTOR_SOMETHING_OR_OTHER": "2",
"SYNAPSE_NOT_CACHE": "BLAH",
}
t.read_config(config, config_dir_path="", data_dir_path="")
self.assertEqual(dict(t.caches.cache_factors), {"something_or_other": 2.0})
def test_config_overrides_environ(self):
"""
Individual cache factors defined in config will take precedence over
ones in the environment.
"""
config = {"caches": {"per_cache_factors": {"foo": 2, "bar": 3}}}
t = TestConfig()
t.caches._environ = {
"SYNAPSE_CACHE_FACTOR_SOMETHING_OR_OTHER": "2",
"SYNAPSE_CACHE_FACTOR_FOO": 1,
}
t.read_config(config, config_dir_path="", data_dir_path="")
self.assertEqual(
dict(t.caches.cache_factors),
{"foo": 2.0, "bar": 3.0, "something_or_other": 2.0},
)