Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

beat.py 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. # -*- coding: utf-8 -*-
  2. """
  3. celery.apps.beat
  4. ~~~~~~~~~~~~~~~~
  5. This module is the 'program-version' of :mod:`celery.beat`.
  6. It does everything necessary to run that module
  7. as an actual application, like installing signal handlers
  8. and so on.
  9. """
  10. from __future__ import absolute_import, unicode_literals
  11. import numbers
  12. import socket
  13. import sys
  14. from celery import VERSION_BANNER, platforms, beat
  15. from celery.utils.imports import qualname
  16. from celery.utils.log import LOG_LEVELS, get_logger
  17. from celery.utils.timeutils import humanize_seconds
  18. __all__ = ['Beat']
  19. STARTUP_INFO_FMT = """
  20. Configuration ->
  21. . broker -> {conninfo}
  22. . loader -> {loader}
  23. . scheduler -> {scheduler}
  24. {scheduler_info}
  25. . logfile -> {logfile}@%{loglevel}
  26. . maxinterval -> {hmax_interval} ({max_interval}s)
  27. """.strip()
  28. logger = get_logger('celery.beat')
  29. class Beat(object):
  30. Service = beat.Service
  31. app = None
  32. def __init__(self, max_interval=None, app=None,
  33. socket_timeout=30, pidfile=None, no_color=None,
  34. loglevel=None, logfile=None, schedule=None,
  35. scheduler_cls=None, redirect_stdouts=None,
  36. redirect_stdouts_level=None, **kwargs):
  37. """Starts the beat task scheduler."""
  38. self.app = app = app or self.app
  39. self.loglevel = self._getopt('log_level', loglevel)
  40. self.logfile = self._getopt('log_file', logfile)
  41. self.schedule = self._getopt('schedule_filename', schedule)
  42. self.scheduler_cls = self._getopt('scheduler', scheduler_cls)
  43. self.redirect_stdouts = self._getopt(
  44. 'redirect_stdouts', redirect_stdouts,
  45. )
  46. self.redirect_stdouts_level = self._getopt(
  47. 'redirect_stdouts_level', redirect_stdouts_level,
  48. )
  49. self.max_interval = max_interval
  50. self.socket_timeout = socket_timeout
  51. self.no_color = no_color
  52. self.colored = app.log.colored(
  53. self.logfile,
  54. enabled=not no_color if no_color is not None else no_color,
  55. )
  56. self.pidfile = pidfile
  57. if not isinstance(self.loglevel, numbers.Integral):
  58. self.loglevel = LOG_LEVELS[self.loglevel.upper()]
  59. def _getopt(self, key, value):
  60. if value is not None:
  61. return value
  62. return self.app.conf.find_value_for_key(key, namespace='celerybeat')
  63. def run(self):
  64. print(str(self.colored.cyan(
  65. 'celery beat v{0} is starting.'.format(VERSION_BANNER))))
  66. self.init_loader()
  67. self.set_process_title()
  68. self.start_scheduler()
  69. def setup_logging(self, colorize=None):
  70. if colorize is None and self.no_color is not None:
  71. colorize = not self.no_color
  72. self.app.log.setup(self.loglevel, self.logfile,
  73. self.redirect_stdouts, self.redirect_stdouts_level,
  74. colorize=colorize)
  75. def start_scheduler(self):
  76. c = self.colored
  77. if self.pidfile:
  78. platforms.create_pidlock(self.pidfile)
  79. beat = self.Service(app=self.app,
  80. max_interval=self.max_interval,
  81. scheduler_cls=self.scheduler_cls,
  82. schedule_filename=self.schedule)
  83. print(str(c.blue('__ ', c.magenta('-'),
  84. c.blue(' ... __ '), c.magenta('-'),
  85. c.blue(' _\n'),
  86. c.reset(self.startup_info(beat)))))
  87. self.setup_logging()
  88. if self.socket_timeout:
  89. logger.debug('Setting default socket timeout to %r',
  90. self.socket_timeout)
  91. socket.setdefaulttimeout(self.socket_timeout)
  92. try:
  93. self.install_sync_handler(beat)
  94. beat.start()
  95. except Exception as exc:
  96. logger.critical('beat raised exception %s: %r',
  97. exc.__class__, exc,
  98. exc_info=True)
  99. def init_loader(self):
  100. # Run the worker init handler.
  101. # (Usually imports task modules and such.)
  102. self.app.loader.init_worker()
  103. self.app.finalize()
  104. def startup_info(self, beat):
  105. scheduler = beat.get_scheduler(lazy=True)
  106. return STARTUP_INFO_FMT.format(
  107. conninfo=self.app.connection().as_uri(),
  108. logfile=self.logfile or '[stderr]',
  109. loglevel=LOG_LEVELS[self.loglevel],
  110. loader=qualname(self.app.loader),
  111. scheduler=qualname(scheduler),
  112. scheduler_info=scheduler.info,
  113. hmax_interval=humanize_seconds(beat.max_interval),
  114. max_interval=beat.max_interval,
  115. )
  116. def set_process_title(self):
  117. arg_start = 'manage' in sys.argv[0] and 2 or 1
  118. platforms.set_process_title(
  119. 'celery beat', info=' '.join(sys.argv[arg_start:]),
  120. )
  121. def install_sync_handler(self, beat):
  122. """Install a `SIGTERM` + `SIGINT` handler that saves
  123. the beat schedule."""
  124. def _sync(signum, frame):
  125. beat.sync()
  126. raise SystemExit()
  127. platforms.signals.update(SIGTERM=_sync, SIGINT=_sync)