cache.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. from datetime import timedelta
  2. from kombu.utils import cached_property
  3. from celery.backends.base import KeyValueStoreBackend
  4. from celery.exceptions import ImproperlyConfigured
  5. from celery.utils import timeutils
  6. from celery.datastructures import LocalCache
  7. _imp = [None]
  8. def import_best_memcache():
  9. if _imp[0] is None:
  10. is_pylibmc = False
  11. try:
  12. import pylibmc as memcache
  13. is_pylibmc = True
  14. except ImportError:
  15. try:
  16. import memcache # noqa
  17. except ImportError:
  18. raise ImproperlyConfigured(
  19. "Memcached backend requires either the 'pylibmc' "
  20. "or 'memcache' library")
  21. _imp[0] = is_pylibmc, memcache
  22. return _imp[0]
  23. def get_best_memcache(*args, **kwargs):
  24. behaviors = kwargs.pop("behaviors", None)
  25. is_pylibmc, memcache = import_best_memcache()
  26. client = memcache.Client(*args, **kwargs)
  27. if is_pylibmc and behaviors is not None:
  28. client.behaviors = behaviors
  29. return client
  30. class DummyClient(object):
  31. def __init__(self, *args, **kwargs):
  32. self.cache = LocalCache(5000)
  33. def get(self, key, *args, **kwargs):
  34. return self.cache.get(key)
  35. def set(self, key, value, *args, **kwargs):
  36. self.cache[key] = value
  37. def delete(self, key, *args, **kwargs):
  38. self.cache.pop(key, None)
  39. backends = {"memcache": lambda: get_best_memcache,
  40. "memcached": lambda: get_best_memcache,
  41. "pylibmc": lambda: get_best_memcache,
  42. "memory": lambda: DummyClient}
  43. class CacheBackend(KeyValueStoreBackend):
  44. def __init__(self, expires=None, backend=None, options={}, **kwargs):
  45. super(CacheBackend, self).__init__(self, **kwargs)
  46. self.expires = expires or self.app.conf.CELERY_TASK_RESULT_EXPIRES
  47. if isinstance(self.expires, timedelta):
  48. self.expires = timeutils.timedelta_seconds(self.expires)
  49. self.options = dict(self.app.conf.CELERY_CACHE_BACKEND_OPTIONS,
  50. **options)
  51. backend = backend or self.app.conf.CELERY_CACHE_BACKEND
  52. self.expires = int(self.expires)
  53. self.backend, _, servers = backend.partition("://")
  54. self.servers = servers.rstrip('/').split(";")
  55. try:
  56. self.Client = backends[self.backend]()
  57. except KeyError:
  58. raise ImproperlyConfigured(
  59. "Unknown cache backend: %s. Please use one of the "
  60. "following backends: %s" % (self.backend,
  61. ", ".join(backends.keys())))
  62. def get(self, key):
  63. return self.client.get(key)
  64. def set(self, key, value):
  65. return self.client.set(key, value, self.expires)
  66. def delete(self, key):
  67. return self.client.delete(key)
  68. @cached_property
  69. def client(self):
  70. return self.Client(self.servers, **self.options)