__init__.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. from functools import wraps
  2. from importlib import import_module
  3. import sys
  4. import traceback
  5. from django.conf import settings
  6. from django.db import close_old_connections
  7. configuration_message = """
  8. Configuring Huey for use with Django
  9. ====================================
  10. Huey was designed to be simple to configure in the general case. For that
  11. reason, huey will "just work" with no configuration at all provided you have
  12. Redis installed and running locally.
  13. On the other hand, you can configure huey manually using the following
  14. setting structure.
  15. The following example uses Redis on localhost, and will run four worker
  16. processes:
  17. HUEY = {
  18. 'name': 'my-app',
  19. 'connection': {'host': 'localhost', 'port': 6379},
  20. 'consumer': {
  21. 'workers': 4,
  22. 'worker_type': 'process', # "thread" or "greenlet" are other options
  23. },
  24. }
  25. If you would like to configure Huey's logger using Django's integrated logging
  26. settings, the logger used by consumer is named "huey.consumer".
  27. Alternatively you can simply assign `settings.HUEY` to an actual `Huey`
  28. object instance:
  29. from huey import RedisHuey
  30. HUEY = RedisHuey('my-app')
  31. """
  32. default_backend_path = 'huey.RedisHuey'
  33. def default_queue_name():
  34. try:
  35. return settings.DATABASE_NAME
  36. except AttributeError:
  37. try:
  38. return settings.DATABASES['default']['NAME']
  39. except KeyError:
  40. return 'huey'
  41. def get_backend(import_path=default_backend_path):
  42. module_path, class_name = import_path.rsplit('.', 1)
  43. module = import_module(module_path)
  44. return getattr(module, class_name)
  45. def config_error(msg):
  46. print(configuration_message)
  47. print('\n\n')
  48. print(msg)
  49. sys.exit(1)
  50. HUEY = getattr(settings, 'HUEY', None)
  51. if HUEY is None:
  52. try:
  53. RedisHuey = get_backend(default_backend_path)
  54. except ImportError:
  55. config_error('Error: Huey could not import the redis backend. '
  56. 'Install `redis-py`.')
  57. else:
  58. HUEY = RedisHuey(default_queue_name())
  59. if isinstance(HUEY, dict):
  60. huey_config = HUEY.copy() # Operate on a copy.
  61. name = huey_config.pop('name', default_queue_name())
  62. backend_path = huey_config.pop('backend_class', default_backend_path)
  63. conn_kwargs = huey_config.pop('connection', {})
  64. try:
  65. del huey_config['consumer'] # Don't need consumer opts here.
  66. except KeyError:
  67. pass
  68. if 'always_eager' not in huey_config:
  69. huey_config['always_eager'] = settings.DEBUG
  70. huey_config.update(conn_kwargs)
  71. try:
  72. backend_cls = get_backend(backend_path)
  73. except (ValueError, ImportError, AttributeError):
  74. config_error('Error: could not import Huey backend:\n%s' % traceback.format_exc())
  75. HUEY = backend_cls(name, **huey_config)
  76. task = HUEY.task
  77. periodic_task = HUEY.periodic_task
  78. lock_task = HUEY.lock_task
  79. enqueue = HUEY.enqueue
  80. restore = HUEY.restore
  81. restore_all = HUEY.restore_all
  82. restore_by_id = HUEY.restore_by_id
  83. revoke = HUEY.revoke
  84. revoke_all = HUEY.revoke_all
  85. revoke_by_id = HUEY.revoke_by_id
  86. is_revoked = HUEY.is_revoked
  87. def close_db(fn):
  88. """Decorator to be used with tasks that may operate on the database."""
  89. @wraps(fn)
  90. def inner(*args, **kwargs):
  91. try:
  92. return fn(*args, **kwargs)
  93. finally:
  94. if not HUEY.always_eager:
  95. close_old_connections()
  96. return inner
  97. def db_task(*args, **kwargs):
  98. def decorator(fn):
  99. ret = task(*args, **kwargs)(close_db(fn))
  100. ret.call_local = fn
  101. return ret
  102. return decorator
  103. def db_periodic_task(*args, **kwargs):
  104. def decorator(fn):
  105. return periodic_task(*args, **kwargs)(close_db(fn))
  106. return decorator