caches: use dogpile for sql_cache_short region.

This commit is contained in:
Marcin Kuzminski 2018-07-12 17:20:03 +02:00
parent 0e05d6dd64
commit 84d673d387
14 changed files with 239 additions and 281 deletions

View file

@ -345,6 +345,10 @@ rc_cache.cache_repo.arguments.filename = /tmp/rc_cache_2
#rc_cache.cache_repo.arguments.db = 1
#rc_cache.cache_repo.arguments.distributed_lock = true
## cache settings for SQL queries
rc_cache.sql_cache_short.backend = dogpile.cache.rc.memory_lru
rc_cache.sql_cache_short.expiration_time = 30
####################################
### BEAKER CACHE ####
@ -355,16 +359,12 @@ rc_cache.cache_repo.arguments.filename = /tmp/rc_cache_2
beaker.cache.data_dir = %(here)s/data/cache/beaker_data
beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
beaker.cache.regions = long_term, sql_cache_short
beaker.cache.regions = long_term
beaker.cache.long_term.type = memorylru_base
beaker.cache.long_term.expire = 172800
beaker.cache.long_term.key_length = 256
beaker.cache.sql_cache_short.type = memorylru_base
beaker.cache.sql_cache_short.expire = 10
beaker.cache.sql_cache_short.key_length = 256
####################################
### BEAKER SESSION ####

View file

@ -320,6 +320,10 @@ rc_cache.cache_repo.arguments.filename = /tmp/rc_cache_2
#rc_cache.cache_repo.arguments.db = 1
#rc_cache.cache_repo.arguments.distributed_lock = true
## cache settings for SQL queries
rc_cache.sql_cache_short.backend = dogpile.cache.rc.memory_lru
rc_cache.sql_cache_short.expiration_time = 30
####################################
### BEAKER CACHE ####
@ -330,16 +334,12 @@ rc_cache.cache_repo.arguments.filename = /tmp/rc_cache_2
beaker.cache.data_dir = %(here)s/data/cache/beaker_data
beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
beaker.cache.regions = long_term, sql_cache_short
beaker.cache.regions = long_term
beaker.cache.long_term.type = memory
beaker.cache.long_term.expire = 172800
beaker.cache.long_term.key_length = 256
beaker.cache.sql_cache_short.type = memory
beaker.cache.sql_cache_short.expire = 10
beaker.cache.sql_cache_short.key_length = 256
####################################
### BEAKER SESSION ####

View file

@ -25,7 +25,7 @@ from rhodecode.model.meta import Session
from rhodecode.model.permission import PermissionModel
from rhodecode.model.ssh_key import SshKeyModel
from rhodecode.tests import (
TestController, clear_all_caches, assert_session_flash)
TestController, clear_cache_regions, assert_session_flash)
def route_path(name, params=None, **kwargs):
@ -221,22 +221,21 @@ class TestAdminPermissionsController(TestController):
def test_index_ips(self):
self.log_user()
response = self.app.get(route_path('admin_permissions_ips'))
# TODO: Test response...
response.mustcontain('All IP addresses are allowed')
def test_add_delete_ips(self):
clear_cache_regions(['sql_cache_short'])
self.log_user()
clear_all_caches()
# ADD
default_user_id = User.get_default_user().user_id
self.app.post(
route_path('edit_user_ips_add', user_id=default_user_id),
params={'new_ip': '127.0.0.0/24', 'csrf_token': self.csrf_token})
params={'new_ip': '0.0.0.0/24', 'csrf_token': self.csrf_token})
response = self.app.get(route_path('admin_permissions_ips'))
response.mustcontain('127.0.0.0/24')
response.mustcontain('127.0.0.0 - 127.0.0.255')
response.mustcontain('0.0.0.0/24')
response.mustcontain('0.0.0.0 - 0.0.0.255')
# DELETE
default_user_id = User.get_default_user().user_id
@ -249,11 +248,11 @@ class TestAdminPermissionsController(TestController):
assert_session_flash(response, 'Removed ip address from user whitelist')
clear_all_caches()
clear_cache_regions(['sql_cache_short'])
response = self.app.get(route_path('admin_permissions_ips'))
response.mustcontain('All IP addresses are allowed')
response.mustcontain(no=['127.0.0.0/24'])
response.mustcontain(no=['127.0.0.0 - 127.0.0.255'])
response.mustcontain(no=['0.0.0.0/24'])
response.mustcontain(no=['0.0.0.0 - 0.0.0.255'])
def test_index_overview(self):
self.log_user()

View file

@ -22,7 +22,7 @@ import pytest
from rhodecode.lib import helpers as h
from rhodecode.tests import (
TestController, clear_all_caches,
TestController, clear_cache_regions,
TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS)
from rhodecode.tests.fixture import Fixture
from rhodecode.tests.utils import AssertResponse
@ -64,7 +64,7 @@ class TestPasswordReset(TestController):
])
def test_password_reset_settings(
self, pwd_reset_setting, show_link, show_reset):
clear_all_caches()
clear_cache_regions()
self.log_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS)
params = {
'csrf_token': self.csrf_token,

View file

@ -31,7 +31,6 @@ from rhodecode.authentication.base import get_authn_registry
from rhodecode.lib import helpers as h
from rhodecode.lib.auth import (
LoginRequired, HasPermissionAllDecorator, CSRFRequired)
from rhodecode.lib.caches import clear_cache_manager
from rhodecode.model.forms import AuthSettingsForm
from rhodecode.model.meta import Session
from rhodecode.model.settings import SettingsModel

View file

@ -427,20 +427,47 @@ def _sanitize_vcs_settings(settings):
def _sanitize_cache_settings(settings):
_string_setting(settings, 'cache_dir',
os.path.join(tempfile.gettempdir(), 'rc_cache'))
# cache_perms
_string_setting(
settings,
'rc_cache.cache_perms.backend',
'dogpile.cache.rc.file_namespace')
_int_setting(
settings,
'rc_cache.cache_perms.expiration_time',
60)
_string_setting(
settings,
'rc_cache.cache_perms.arguments.filename',
os.path.join(tempfile.gettempdir(), 'rc_cache_1'))
_string_setting(settings, 'rc_cache.cache_perms.backend',
'dogpile.cache.rc.file_namespace')
_int_setting(settings, 'rc_cache.cache_perms.expiration_time',
60)
_string_setting(settings, 'rc_cache.cache_perms.arguments.filename',
os.path.join(tempfile.gettempdir(), 'rc_cache_1'))
# cache_repo
_string_setting(
settings,
'rc_cache.cache_repo.backend',
'dogpile.cache.rc.file_namespace')
_int_setting(
settings,
'rc_cache.cache_repo.expiration_time',
60)
_string_setting(
settings,
'rc_cache.cache_repo.arguments.filename',
os.path.join(tempfile.gettempdir(), 'rc_cache_2'))
_string_setting(settings, 'rc_cache.cache_repo.backend',
'dogpile.cache.rc.file_namespace')
_int_setting(settings, 'rc_cache.cache_repo.expiration_time',
60)
_string_setting(settings, 'rc_cache.cache_repo.arguments.filename',
os.path.join(tempfile.gettempdir(), 'rc_cache_2'))
# sql_cache_short
_string_setting(
settings,
'rc_cache.sql_cache_short.backend',
'dogpile.cache.rc.memory_lru')
_int_setting(
settings,
'rc_cache.sql_cache_short.expiration_time',
30)
_int_setting(
settings,
'rc_cache.sql_cache_short.max_size',
10000)
def _int_setting(settings, name, default):

View file

@ -23,7 +23,7 @@ import beaker
import logging
import threading
from beaker.cache import _cache_decorate, cache_regions, region_invalidate
from beaker.cache import _cache_decorate, region_invalidate
from sqlalchemy.exc import IntegrityError
from rhodecode.lib.utils import safe_str, sha1
@ -84,44 +84,6 @@ def configure_cache_region(
beaker.cache.cache_regions[region_name] = region_settings
def get_cache_manager(region_name, cache_name, custom_ttl=None):
"""
Creates a Beaker cache manager. Such instance can be used like that::
_namespace = caches.get_repo_namespace_key(caches.XXX, repo_name)
cache_manager = caches.get_cache_manager('some_namespace_name', _namespace)
_cache_key = caches.compute_key_from_params(repo_name, commit.raw_id)
def heavy_compute():
...
result = cache_manager.get(_cache_key, createfunc=heavy_compute)
:param region_name: region from ini file
:param cache_name: custom cache name, usually prefix+repo_name. eg
file_switcher_repo1
:param custom_ttl: override .ini file timeout on this cache
:return: instance of cache manager
"""
cache_config = cache_regions.get(region_name, DEFAULT_CACHE_MANAGER_CONFIG)
if custom_ttl:
log.debug('Updating region %s with custom ttl: %s',
region_name, custom_ttl)
cache_config.update({'expire': custom_ttl})
return beaker.cache.Cache._get_cache(cache_name, cache_config)
def clear_cache_manager(cache_manager):
"""
namespace = 'foobar'
cache_manager = get_cache_manager('some_namespace_name', namespace)
clear_cache_manager(cache_manager)
"""
log.debug('Clearing all values for cache manager %s', cache_manager)
cache_manager.clear()
def compute_key_from_params(*args):
"""
Helper to compute key from given params to be used in cache manager

View file

@ -18,16 +18,16 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
"""
caching_query.py
"""caching_query.py
Represent persistence structures which allow the usage of
Beaker caching with SQLAlchemy.
Represent functions and classes
which allow the usage of Dogpile caching with SQLAlchemy.
Introduces a query option called FromCache.
The three new concepts introduced here are:
* CachingQuery - a Query subclass that caches and
retrieves results in/from Beaker.
retrieves results in/from dogpile.cache.
* FromCache - a query option that establishes caching
parameters on a Query
* RelationshipCache - a variant of FromCache which is specific
@ -36,57 +36,44 @@ The three new concepts introduced here are:
a Query.
The rest of what's here are standard SQLAlchemy and
Beaker constructs.
dogpile.cache constructs.
"""
import beaker
from beaker.exceptions import BeakerException
from sqlalchemy.orm.interfaces import MapperOption
from sqlalchemy.orm.query import Query
from sqlalchemy.sql import visitors
from dogpile.cache.api import NO_VALUE
from rhodecode.lib.utils2 import safe_str
class CachingQuery(Query):
"""A Query subclass which optionally loads full results from a Beaker
"""A Query subclass which optionally loads full results from a dogpile
cache region.
The CachingQuery stores additional state that allows it to consult
a Beaker cache before accessing the database:
* A "region", which is a cache region argument passed to a
Beaker CacheManager, specifies a particular cache configuration
(including backend implementation, expiration times, etc.)
* A "namespace", which is a qualifying name that identifies a
group of keys within the cache. A query that filters on a name
might use the name "by_name", a query that filters on a date range
to a joined table might use the name "related_date_range".
When the above state is present, a Beaker cache is retrieved.
The "namespace" name is first concatenated with
a string composed of the individual entities and columns the Query
requests, i.e. such as ``Query(User.id, User.name)``.
The Beaker cache is then loaded from the cache manager based
on the region and composed namespace. The key within the cache
itself is then constructed against the bind parameters specified
by this query, which are usually literals defined in the
WHERE clause.
The CachingQuery optionally stores additional state that allows it to consult
a dogpile.cache cache before accessing the database, in the form
of a FromCache or RelationshipCache object. Each of these objects
refer to the name of a :class:`dogpile.cache.Region` that's been configured
and stored in a lookup dictionary. When such an object has associated
itself with the CachingQuery, the corresponding :class:`dogpile.cache.Region`
is used to locate a cached result. If none is present, then the
Query is invoked normally, the results being cached.
The FromCache and RelationshipCache mapper options below represent
the "public" method of configuring this state upon the CachingQuery.
"""
def _get_region(self):
from rhodecode.lib.rc_cache import region_meta
return region_meta.dogpile_cache_regions
def __init__(self, manager, *args, **kw):
self.cache_manager = manager
def __init__(self, regions, *args, **kw):
self.cache_regions = regions or self._get_region()
Query.__init__(self, *args, **kw)
def __iter__(self):
"""override __iter__ to pull results from Beaker
"""override __iter__ to pull results from dogpile
if particular attributes have been configured.
Note that this approach does *not* detach the loaded objects from
@ -98,109 +85,121 @@ class CachingQuery(Query):
in the cache are not the same ones in the current Session.
"""
if hasattr(self, '_cache_parameters'):
super_ = super(CachingQuery, self)
def caching_query():
return list(Query.__iter__(self))
return self.get_value(createfunc=caching_query)
if hasattr(self, '_cache_region'):
return self.get_value(createfunc=lambda: list(super_.__iter__()))
else:
return Query.__iter__(self)
return super_.__iter__()
def _execute_and_instances(self, context):
"""override _execute_and_instances to pull results from dogpile
if the query is invoked directly from an external context.
This method is necessary in order to maintain compatibility
with the "baked query" system now used by default in some
relationship loader scenarios. Note also the
RelationshipCache._generate_cache_key method which enables
the baked query to be used within lazy loads.
.. versionadded:: 1.2.7
"""
super_ = super(CachingQuery, self)
if context.query is not self and hasattr(self, '_cache_region'):
# special logic called when the Query._execute_and_instances()
# method is called directly from the baked query
return self.get_value(
createfunc=lambda: list(
super_._execute_and_instances(context)
)
)
else:
return super_._execute_and_instances(context)
def _get_cache_plus_key(self):
"""Return a cache region plus key."""
dogpile_region = self.cache_regions[self._cache_region.region]
if self._cache_region.cache_key:
key = self._cache_region.cache_key
else:
key = _key_from_query(self)
return dogpile_region, key
def invalidate(self):
"""Invalidate the value represented by this Query."""
"""Invalidate the cache value represented by this Query."""
cache, cache_key = _get_cache_parameters(self)
cache.remove(cache_key)
dogpile_region, cache_key = self._get_cache_plus_key()
dogpile_region.delete(cache_key)
def get_value(self, merge=True, createfunc=None):
def get_value(self, merge=True, createfunc=None,
expiration_time=None, ignore_expiration=False):
"""Return the value from the cache for this query.
Raise KeyError if no value present and no
createfunc specified.
"""
cache, cache_key = _get_cache_parameters(self)
ret = cache.get_value(cache_key, createfunc=createfunc)
dogpile_region, cache_key = self._get_cache_plus_key()
# ignore_expiration means, if the value is in the cache
# but is expired, return it anyway. This doesn't make sense
# with createfunc, which says, if the value is expired, generate
# a new value.
assert not ignore_expiration or not createfunc, \
"Can't ignore expiration and also provide createfunc"
if ignore_expiration or not createfunc:
cached_value = dogpile_region.get(cache_key,
expiration_time=expiration_time,
ignore_expiration=ignore_expiration)
else:
cached_value = dogpile_region.get_or_create(
cache_key,
createfunc,
expiration_time=expiration_time
)
if cached_value is NO_VALUE:
raise KeyError(cache_key)
if merge:
ret = self.merge_result(ret, load=False)
return ret
cached_value = self.merge_result(cached_value, load=False)
return cached_value
def set_value(self, value):
"""Set the value in the cache for this query."""
cache, cache_key = _get_cache_parameters(self)
cache.put(cache_key, value)
dogpile_region, cache_key = self._get_cache_plus_key()
dogpile_region.set(cache_key, value)
def query_callable(manager, query_cls=CachingQuery):
def query_callable(regions=None, query_cls=CachingQuery):
def query(*arg, **kw):
return query_cls(manager, *arg, **kw)
return query_cls(regions, *arg, **kw)
return query
def get_cache_region(name, region):
if region not in beaker.cache.cache_regions:
raise BeakerException('Cache region `%s` not configured '
'Check if proper cache settings are in the .ini files' % region)
kw = beaker.cache.cache_regions[region]
return beaker.cache.Cache._get_cache(name, kw)
def _key_from_query(query, qualifier=None):
"""Given a Query, create a cache key.
def _get_cache_parameters(query):
"""For a query with cache_region and cache_namespace configured,
return the correspoinding Cache instance and cache key, based
on this query's current criterion and parameter values.
There are many approaches to this; here we use the simplest,
which is to create an md5 hash of the text of the SQL statement,
combined with stringified versions of all the bound parameters
within it. There's a bit of a performance hit with
compiling out "query.statement" here; other approaches include
setting up an explicit cache key with a particular Query,
then combining that with the bound parameter values.
"""
if not hasattr(query, '_cache_parameters'):
raise ValueError("This Query does not have caching "
"parameters configured.")
region, namespace, cache_key = query._cache_parameters
stmt = query.with_labels().statement
compiled = stmt.compile()
params = compiled.params
namespace = _namespace_from_query(namespace, query)
if cache_key is None:
# cache key - the value arguments from this query's parameters.
args = [safe_str(x) for x in _params_from_query(query)]
args.extend(filter(lambda k: k not in ['None', None, u'None'],
[str(query._limit), str(query._offset)]))
cache_key = " ".join(args)
if cache_key is None:
raise Exception('Cache key cannot be None')
# get cache
#cache = query.cache_manager.get_cache_region(namespace, region)
cache = get_cache_region(namespace, region)
# optional - hash the cache_key too for consistent length
# import uuid
# cache_key= str(uuid.uuid5(uuid.NAMESPACE_DNS, cache_key))
return cache, cache_key
def _namespace_from_query(namespace, query):
# cache namespace - the token handed in by the
# option + class we're querying against
namespace = " ".join([namespace] + [str(x) for x in query._entities])
# memcached wants this
namespace = namespace.replace(' ', '_')
return namespace
def _set_cache_parameters(query, region, namespace, cache_key):
if hasattr(query, '_cache_parameters'):
region, namespace, cache_key = query._cache_parameters
raise ValueError("This query is already configured "
"for region %r namespace %r" %
(region, namespace))
query._cache_parameters = region, namespace, cache_key
# here we return the key as a long string. our "key mangler"
# set up with the region will boil it down to an md5.
return " ".join(
[safe_str(compiled)] +
[safe_str(params[k]) for k in sorted(params)])
class FromCache(MapperOption):
@ -208,15 +207,12 @@ class FromCache(MapperOption):
propagate_to_loaders = False
def __init__(self, region, namespace, cache_key=None):
def __init__(self, region="sql_cache_short", cache_key=None):
"""Construct a new FromCache.
:param region: the cache region. Should be a
region configured in the Beaker CacheManager.
:param namespace: the cache namespace. Should
be a name uniquely describing the target Query's
lexical structure.
region configured in the dictionary of dogpile
regions.
:param cache_key: optional. A string cache key
that will serve as the key to the query. Use this
@ -226,14 +222,11 @@ class FromCache(MapperOption):
"""
self.region = region
self.namespace = namespace
self.cache_key = cache_key
def process_query(self, query):
"""Process a Query during normal loading operation."""
_set_cache_parameters(query, self.region, self.namespace,
self.cache_key)
query._cache_region = self
class RelationshipCache(MapperOption):
@ -242,27 +235,39 @@ class RelationshipCache(MapperOption):
propagate_to_loaders = True
def __init__(self, region, namespace, attribute):
def __init__(self, attribute, region="sql_cache_short", cache_key=None):
"""Construct a new RelationshipCache.
:param region: the cache region. Should be a
region configured in the Beaker CacheManager.
:param namespace: the cache namespace. Should
be a name uniquely describing the target Query's
lexical structure.
:param attribute: A Class.attribute which
indicates a particular class relationship() whose
lazy loader should be pulled from the cache.
:param region: name of the cache region.
:param cache_key: optional. A string cache key
that will serve as the key to the query, bypassing
the usual means of forming a key from the Query itself.
"""
self.region = region
self.namespace = namespace
self.cache_key = cache_key
self._relationship_options = {
(attribute.property.parent.class_, attribute.property.key): self
}
def _generate_cache_key(self, path):
"""Indicate to the lazy-loader strategy that a "baked" query
may be used by returning ``None``.
If this method is omitted, the default implementation of
:class:`.MapperOption._generate_cache_key` takes place, which
returns ``False`` to disable the "baked" query from being used.
.. versionadded:: 1.2.7
"""
return None
def process_query_conditionally(self, query):
"""Process a Query that is used within a lazy loader.
@ -271,17 +276,14 @@ class RelationshipCache(MapperOption):
"""
if query._current_path:
mapper, key = query._current_path[-2:]
mapper, prop = query._current_path[-2:]
key = prop.key
for cls in mapper.class_.__mro__:
if (cls, key) in self._relationship_options:
relationship_option = \
self._relationship_options[(cls, key)]
_set_cache_parameters(
query,
relationship_option.region,
relationship_option.namespace,
None)
relationship_option = self._relationship_options[(cls, key)]
query._cache_region = relationship_option
break
def and_(self, option):
"""Chain another RelationshipCache option to this one.
@ -294,32 +296,3 @@ class RelationshipCache(MapperOption):
self._relationship_options.update(option._relationship_options)
return self
def _params_from_query(query):
"""Pull the bind parameter values from a query.
This takes into account any scalar attribute bindparam set up.
E.g. params_from_query(query.filter(Cls.foo==5).filter(Cls.bar==7)))
would return [5, 7].
"""
v = []
def visit_bindparam(bind):
if bind.key in query._params:
value = query._params[bind.key]
elif bind.callable:
# lazyloader may dig a callable in here, intended
# to late-evaluate params after autoflush is called.
# convert to a scalar value.
value = bind.callable()
else:
value = bind.value
v.append(value)
if query._criterion is not None:
visitors.traverse(query._criterion, {}, {'bindparam':visit_bindparam})
for f in query._from_obj:
visitors.traverse(f, {}, {'bindparam':visit_bindparam})
return v

View file

@ -690,7 +690,7 @@ class User(Base, BaseModel):
.filter(UserApiKeys.role == UserApiKeys.ROLE_FEED)
if cache:
feed_tokens = feed_tokens.options(
FromCache("long_term", "get_user_feed_token_%s" % self.user_id))
FromCache("sql_cache_short", "get_user_feed_token_%s" % self.user_id))
feed_tokens = feed_tokens.all()
if feed_tokens:

View file

@ -24,27 +24,22 @@ SQLAlchemy Metadata and Session object
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
from beaker import cache
from rhodecode.lib import caching_query
# Beaker CacheManager. A home base for cache configurations.
cache_manager = cache.CacheManager()
__all__ = ['Base', 'Session']
#
# SQLAlchemy session manager. Updated by model.init_model()
#
# scoped_session. Apply our custom CachingQuery class to it,
# using a callable that will associate the dictionary
# of regions with the Query.
# to use cache use this in query
# .options(FromCache("sqlalchemy_cache_type", "cachekey"))
Session = scoped_session(
sessionmaker(
query_cls=caching_query.query_callable(cache_manager),
query_cls=caching_query.query_callable(),
expire_on_commit=True,
)
)
# The declarative Base
Base = declarative_base()
#to use cache use this in query
#.options(FromCache("sqlalchemy_cache_type", "cachekey"))

View file

@ -21,11 +21,12 @@
import os
import hashlib
import logging
import time
from collections import namedtuple
from functools import wraps
import bleach
from rhodecode.lib import caches
from rhodecode.lib import caches, rc_cache
from rhodecode.lib.utils2 import (
Optional, AttributeDict, safe_str, remove_prefix, str2bool)
from rhodecode.lib.vcs.backends import base
@ -206,13 +207,17 @@ class SettingsModel(BaseModel):
return res
def invalidate_settings_cache(self):
namespace = 'rhodecode_settings'
cache_manager = caches.get_cache_manager('sql_cache_short', namespace)
caches.clear_cache_manager(cache_manager)
# NOTE:(marcink) we flush the whole sql_cache_short region, because it
# reads different settings etc. It's little too much but those caches are
# anyway very short lived and it's a safest way.
region = rc_cache.get_or_create_region('sql_cache_short')
region.invalidate()
def get_all_settings(self, cache=False):
region = rc_cache.get_or_create_region('sql_cache_short')
def _compute():
@region.cache_on_arguments(should_cache_fn=lambda v: cache)
def _get_all_settings(name, key):
q = self._get_settings_query()
if not q:
raise Exception('Could not get application settings !')
@ -223,20 +228,14 @@ class SettingsModel(BaseModel):
}
return settings
if cache:
log.debug('Fetching app settings using cache')
repo = self._get_repo(self.repo) if self.repo else None
namespace = 'rhodecode_settings'
cache_manager = caches.get_cache_manager(
'sql_cache_short', namespace)
_cache_key = (
"get_repo_{}_settings".format(repo.repo_id)
if repo else "get_app_settings")
repo = self._get_repo(self.repo) if self.repo else None
key = "settings_repo.{}".format(repo.repo_id) if repo else "settings_app"
start = time.time()
result = _get_all_settings('rhodecode_settings', key)
total = time.time() - start
log.debug('Fetching app settings for key: %s took: %.3fs', key, total)
return cache_manager.get(_cache_key, createfunc=_compute)
else:
return _compute()
return result
def get_auth_settings(self):
q = self._get_settings_query()

View file

@ -41,7 +41,7 @@ log = logging.getLogger(__name__)
__all__ = [
'get_new_dir', 'TestController',
'link_to', 'clear_all_caches',
'link_to', 'clear_cache_regions',
'assert_session_flash', 'login_user', 'no_newline_id_generator',
'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'SVN_REPO',
'NEW_HG_REPO', 'NEW_GIT_REPO',
@ -95,10 +95,12 @@ TEST_HG_REPO_PULL = jn(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
TEST_REPO_PREFIX = 'vcs-test'
def clear_all_caches():
from beaker.cache import cache_managers
for _cache in cache_managers.values():
_cache.clear()
def clear_cache_regions(regions=None):
# dogpile
from rhodecode.lib.rc_cache import region_meta
for region_name, region in region_meta.dogpile_cache_regions.items():
if not regions or region_name in regions:
region.invalidate()
def get_new_dir(title):

View file

@ -70,8 +70,7 @@ def disable_hooks(request, hooks):
ui_settings.invalidate()
ui_settings = session.query(db.RhodeCodeUi).options(
caching_query.FromCache(
'sql_cache_short', 'get_hook_settings', 'get_hook_settings'))
caching_query.FromCache('sql_cache_short', 'get_hook_settings'))
ui_settings.invalidate()
@request.addfinalizer

View file

@ -292,15 +292,12 @@ cache_dir = %(here)s/data
beaker.cache.data_dir = %(here)s/rc/data/cache/beaker_data
beaker.cache.lock_dir = %(here)s/rc/data/cache/beaker_lock
beaker.cache.regions = long_term, sql_cache_short
beaker.cache.regions = long_term
beaker.cache.long_term.type = memory
beaker.cache.long_term.expire = 36000
beaker.cache.long_term.key_length = 256
beaker.cache.sql_cache_short.type = memory
beaker.cache.sql_cache_short.expire = 1
beaker.cache.sql_cache_short.key_length = 256
#####################################
### DOGPILE CACHE ####
@ -311,6 +308,12 @@ rc_cache.cache_perms.backend = dogpile.cache.rc.file_namespace
rc_cache.cache_perms.expiration_time = 0
rc_cache.cache_perms.arguments.filename = /tmp/rc_cache_1
## cache settings for SQL queries
rc_cache.sql_cache_short.backend = dogpile.cache.rc.memory_lru
rc_cache.sql_cache_short.expiration_time = 0
####################################
### BEAKER SESSION ####
####################################