From a6291394256aa758d74eec9ce0cfae8aea6475f2 Mon Sep 17 00:00:00 2001 From: Nick Pope Date: Sat, 15 Aug 2020 21:34:32 +0100 Subject: [PATCH] Refs #29887, Refs #24212 -- Added servers configuration hook for memcached backends. The servers property can be overridden to allow memcached backends to alter the server configuration prior to it being passed to instantiate the client. This allows avoidance of documentation for per-backend differences, e.g. stripping the 'unix:' prefix for pylibmc. --- django/core/cache/backends/memcached.py | 13 ++++++++++++- docs/topics/cache.txt | 9 --------- tests/cache/tests.py | 12 ++++++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/django/core/cache/backends/memcached.py b/django/core/cache/backends/memcached.py index ed3f2af4929..6a7ced6073d 100644 --- a/django/core/cache/backends/memcached.py +++ b/django/core/cache/backends/memcached.py @@ -26,12 +26,16 @@ class BaseMemcachedCache(BaseCache): self._class = library.Client self._options = params.get('OPTIONS') or {} + @property + def client_servers(self): + return self._servers + @cached_property def _cache(self): """ Implement transparent thread-safe access to a memcached client. """ - return self._class(self._servers, **self._options) + return self._class(self.client_servers, **self._options) def get_backend_timeout(self, timeout=DEFAULT_TIMEOUT): """ @@ -192,6 +196,13 @@ class PyLibMCCache(BaseMemcachedCache): import pylibmc super().__init__(server, params, library=pylibmc, value_not_found_exception=pylibmc.NotFound) + @property + def client_servers(self): + output = [] + for server in self._servers: + output.append(server[5:] if server.startswith('unix:') else server) + return output + def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None): key = self.make_key(key, version=version) self.validate_key(key) diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt index cc9b22ae652..ccaa82277f0 100644 --- a/docs/topics/cache.txt +++ b/docs/topics/cache.txt @@ -114,15 +114,6 @@ In this example, Memcached is available through a local Unix socket file } } -When using the ``pylibmc`` binding, do not include the ``unix:/`` prefix:: - - CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', - 'LOCATION': '/tmp/memcached.sock', - } - } - One excellent feature of Memcached is its ability to share a cache over multiple servers. This means you can run Memcached daemons on multiple machines, and the program will treat the group of machines as a *single* diff --git a/tests/cache/tests.py b/tests/cache/tests.py index 3aa01ccced9..93f0d87ecb9 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -1441,6 +1441,18 @@ class PyLibMCCacheTests(BaseMemcachedTests, TestCase): self.assertTrue(cache._cache.binary) self.assertEqual(cache._cache.behaviors['tcp_nodelay'], int(True)) + def test_pylibmc_client_servers(self): + backend = self.base_params['BACKEND'] + tests = [ + ('unix:/run/memcached/socket', '/run/memcached/socket'), + ('/run/memcached/socket', '/run/memcached/socket'), + ('127.0.0.1:11211', '127.0.0.1:11211'), + ] + for location, expected in tests: + settings = {'default': {'BACKEND': backend, 'LOCATION': location}} + with self.subTest(location), self.settings(CACHES=settings): + self.assertEqual(cache.client_servers, [expected]) + @override_settings(CACHES=caches_setting_for_tests( BACKEND='django.core.cache.backends.filebased.FileBasedCache',