Skip to content

Commit

Permalink
Merge a018d6d into 34a84f7
Browse files Browse the repository at this point in the history
  • Loading branch information
gergelypolonkai committed Feb 23, 2019
2 parents 34a84f7 + a018d6d commit baff118
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 24 deletions.
22 changes: 20 additions & 2 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,14 @@ The following configuration values exist for Flask-Caching:
``CACHE_REDIS_HOST`` A Redis server host. Used only for RedisCache.
``CACHE_REDIS_PORT`` A Redis server port. Default is 6379.
Used only for RedisCache.
``CACHE_REDIS_PASSWORD`` A Redis password for server. Used only for RedisCache.
``CACHE_REDIS_PASSWORD`` A Redis password for server. Used only for RedisCache and
RedisSentinelCache.
``CACHE_REDIS_DB`` A Redis db (zero-based number index). Default is 0.
Used only for RedisCache.
Used only for RedisCache and RedisSentinelCache.
``CACHE_REDIS_SENTINELS`` A list or a tuple of Redis sentinel addresses. Used only for
RedisSentinelCache.
``CACHE_REDIS_SENTINEL_MASTER`` The name of the master server in a sentinel configuration. Used
only for RedisSentinelCache.
``CACHE_DIR`` Directory to store cache. Used only for
FileSystemCache.
``CACHE_REDIS_URL`` URL to connect to Redis server.
Expand Down Expand Up @@ -393,6 +398,19 @@ Set ``CACHE_TYPE`` to ``redis`` to use this type.

Entries in CACHE_OPTIONS are passed to the redis client as ``**kwargs``

RedisSentinelCache
``````````````````

Set ``CACHE_TYPE`` to ``redissentinel`` to use this type.

- CACHE_REDIS_SENTINELS
- CACHE_REDIS_SENTINEL_MASTER
- CACHE_REDIS_PASSWORD
- CACHE_KEY_PREFIX
- CACHE_REDIS_DB

Entries in CACHE_OPTIONS are passed to the redis client as ``**kwargs``

MemcachedCache
``````````````

Expand Down
20 changes: 17 additions & 3 deletions flask_caching/backends/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
except ImportError:
has_UWSGICache = False

from .clients import SASLMemcachedCache, SpreadSASLMemcachedCache
from .clients import (SASLMemcachedCache, SpreadSASLMemcachedCache,
RedisSentinelCache)

__all__ = ('null', 'simple', 'filesystem', 'redis', 'uwsgi', 'memcached',
'saslmemcached', 'gaememcached', 'spreadsaslmemcached')
__all__ = ('null', 'simple', 'filesystem', 'redis', 'redissentinel', 'uwsgi',
'memcached', 'saslmemcached', 'gaememcached', 'spreadsaslmemcached')


def null(app, config, args, kwargs):
Expand Down Expand Up @@ -70,6 +71,19 @@ def redis(app, config, args, kwargs):
return RedisCache(*args, **kwargs)


def redissentinel(app, config, args, kwargs):
kwargs.update(dict(
sentinels=config.get('CACHE_REDIS_SENTINELS', [('127.0.0.1', 26379)]),
master=config.get('CACHE_REDIS_SENTINEL_MASTER', 'mymaster'),
password=config.get('CACHE_REDIS_PASSWORD', None),
sentinel_password=config.get('CACHE_REDIS_SENTINEL_PASSWORD', None),
key_prefix=config.get('CACHE_KEY_PREFIX', None),
db=config.get('CACHE_REDIS_DB', 0)
))

return RedisSentinelCache(*args, **kwargs)


def uwsgi(app, config, args, kwargs):
if not has_UWSGICache:
raise NotImplementedError("UWSGICache backend is not available, "
Expand Down
38 changes: 20 additions & 18 deletions flask_caching/backends/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -574,10 +574,12 @@ def __init__(self, host='localhost', port=6379, password=None,
if kwargs.get('decode_responses', None):
raise ValueError('decode_responses is not supported by '
'RedisCache.')
self._client = redis.Redis(host=host, port=port, password=password,
db=db, **kwargs)
client = redis.Redis(host=host, port=port, password=password,
db=db, **kwargs)
else:
self._client = host
client = host

self._write_client = self._read_clients = client
self.key_prefix = key_prefix or ''

def _normalize_timeout(self, timeout):
Expand Down Expand Up @@ -613,37 +615,37 @@ def load_object(self, value):
return value

def get(self, key):
return self.load_object(self._client.get(self.key_prefix + key))
return self.load_object(self._read_clients.get(self.key_prefix + key))

def get_many(self, *keys):
if self.key_prefix:
keys = [self.key_prefix + key for key in keys]
return [self.load_object(x) for x in self._client.mget(keys)]
return [self.load_object(x) for x in self._read_clients.mget(keys)]

def set(self, key, value, timeout=None):
timeout = self._normalize_timeout(timeout)
dump = self.dump_object(value)
if timeout == -1:
result = self._client.set(name=self.key_prefix + key,
result = self._write_client.set(name=self.key_prefix + key,
value=dump)
else:
result = self._client.setex(name=self.key_prefix + key,
result = self._write_client.setex(name=self.key_prefix + key,
value=dump, time=timeout)
return result

def add(self, key, value, timeout=None):
timeout = self._normalize_timeout(timeout)
dump = self.dump_object(value)
return (
self._client.setnx(name=self.key_prefix + key, value=dump) and
self._client.expire(name=self.key_prefix + key, time=timeout)
self._write_client.setnx(name=self.key_prefix + key, value=dump) and
self._write_client.expire(name=self.key_prefix + key, time=timeout)
)

def set_many(self, mapping, timeout=None):
timeout = self._normalize_timeout(timeout)
# Use transaction=False to batch without calling redis MULTI
# which is not supported by twemproxy
pipe = self._client.pipeline(transaction=False)
pipe = self._write_client.pipeline(transaction=False)

for key, value in _items(mapping):
dump = self.dump_object(value)
Expand All @@ -655,33 +657,33 @@ def set_many(self, mapping, timeout=None):
return pipe.execute()

def delete(self, key):
return self._client.delete(self.key_prefix + key)
return self._write_client.delete(self.key_prefix + key)

def delete_many(self, *keys):
if not keys:
return
if self.key_prefix:
keys = [self.key_prefix + key for key in keys]
return self._client.delete(*keys)
return self._write_client.delete(*keys)

def has(self, key):
return self._client.exists(self.key_prefix + key)
return self._read_clients.exists(self.key_prefix + key)

def clear(self):
status = False
if self.key_prefix:
keys = self._client.keys(self.key_prefix + '*')
keys = self._read_clients.keys(self.key_prefix + '*')
if keys:
status = self._client.delete(*keys)
status = self._write_client.delete(*keys)
else:
status = self._client.flushdb()
status = self._write_client.flushdb()
return status

def inc(self, key, delta=1):
return self._client.incr(name=self.key_prefix + key, amount=delta)
return self._write_client.incr(name=self.key_prefix + key, amount=delta)

def dec(self, key, delta=1):
return self._client.decr(name=self.key_prefix + key, amount=delta)
return self._write_client.decr(name=self.key_prefix + key, amount=delta)


class FileSystemCache(BaseCache):
Expand Down
36 changes: 35 additions & 1 deletion flask_caching/backends/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,45 @@
:license: BSD, see LICENSE for more details.
"""
import pickle
from flask_caching.backends.cache import BaseCache, MemcachedCache
from flask_caching.backends.cache import BaseCache, MemcachedCache, RedisCache

from flask_caching._compat import PY2, range_type


class RedisSentinelCache(RedisCache):
def __init__(self, sentinels=None, master=None, password=None,
db=0, default_timeout=300, key_prefix=None, **kwargs):
super(RedisSentinelCache, self).__init__(default_timeout)

try:
import redis.sentinel
except ImportError:
raise RuntimeError('no redis module found')

if kwargs.get('decode_responses', None):
raise ValueError('decode_responses is not supported by '
'RedisCache.')

sentinels = sentinels or [('127.0.0.1', 26379)]
sentinel_kwargs = {key[9:]: value
for key, value in kwargs.items()
if key.startswith('sentinel_')}
kwargs = {key[9:]: value
for key, value in kwargs.items()
if not key.startswith('sentinel_')}

sentinel = redis.sentinel.Sentinel(
sentinels=sentinels,
password=password,
db=db,
sentinel_kwargs=sentinel_kwargs, **kwargs)

self._write_client = sentinel.master_for(master)
self._read_clients = sentinel.slave_for(master)

self.key_prefix = key_prefix or ''


class SASLMemcachedCache(MemcachedCache):
def __init__(self, servers=None, default_timeout=300, key_prefix=None,
username=None, password=None, **kwargs):
Expand Down

0 comments on commit baff118

Please sign in to comment.