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.

loops.py 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. """
  2. celery.worker.loop
  3. ~~~~~~~~~~~~~~~~~~
  4. The consumers highly-optimized inner loop.
  5. """
  6. from __future__ import absolute_import
  7. import socket
  8. from celery.bootsteps import RUN
  9. from celery.exceptions import WorkerShutdown, WorkerTerminate, WorkerLostError
  10. from celery.utils.log import get_logger
  11. from . import state
  12. __all__ = ['asynloop', 'synloop']
  13. logger = get_logger(__name__)
  14. error = logger.error
  15. def asynloop(obj, connection, consumer, blueprint, hub, qos,
  16. heartbeat, clock, hbrate=2.0, RUN=RUN):
  17. """Non-blocking event loop consuming messages until connection is lost,
  18. or shutdown is requested."""
  19. update_qos = qos.update
  20. hbtick = connection.heartbeat_check
  21. errors = connection.connection_errors
  22. heartbeat = connection.get_heartbeat_interval() # negotiated
  23. on_task_received = obj.create_task_handler()
  24. if heartbeat and connection.supports_heartbeats:
  25. hub.call_repeatedly(heartbeat / hbrate, hbtick, hbrate)
  26. consumer.callbacks = [on_task_received]
  27. consumer.consume()
  28. obj.on_ready()
  29. obj.controller.register_with_event_loop(hub)
  30. obj.register_with_event_loop(hub)
  31. # did_start_ok will verify that pool processes were able to start,
  32. # but this will only work the first time we start, as
  33. # maxtasksperchild will mess up metrics.
  34. if not obj.restart_count and not obj.pool.did_start_ok():
  35. raise WorkerLostError('Could not start worker processes')
  36. # consumer.consume() may have prefetched up to our
  37. # limit - drain an event so we are in a clean state
  38. # prior to starting our event loop.
  39. if connection.transport.driver_type == 'amqp':
  40. hub.call_soon(connection.drain_events)
  41. # FIXME: Use loop.run_forever
  42. # Tried and works, but no time to test properly before release.
  43. hub.propagate_errors = errors
  44. loop = hub.create_loop()
  45. try:
  46. while blueprint.state == RUN and obj.connection:
  47. # shutdown if signal handlers told us to.
  48. if state.should_stop:
  49. raise WorkerShutdown()
  50. elif state.should_terminate:
  51. raise WorkerTerminate()
  52. # We only update QoS when there is no more messages to read.
  53. # This groups together qos calls, and makes sure that remote
  54. # control commands will be prioritized over task messages.
  55. if qos.prev != qos.value:
  56. update_qos()
  57. try:
  58. next(loop)
  59. except StopIteration:
  60. loop = hub.create_loop()
  61. finally:
  62. try:
  63. hub.reset()
  64. except Exception as exc:
  65. error(
  66. 'Error cleaning up after event loop: %r', exc, exc_info=1,
  67. )
  68. def synloop(obj, connection, consumer, blueprint, hub, qos,
  69. heartbeat, clock, hbrate=2.0, **kwargs):
  70. """Fallback blocking event loop for transports that doesn't support AIO."""
  71. on_task_received = obj.create_task_handler()
  72. consumer.register_callback(on_task_received)
  73. consumer.consume()
  74. obj.on_ready()
  75. while blueprint.state == RUN and obj.connection:
  76. state.maybe_shutdown()
  77. if qos.prev != qos.value:
  78. qos.update()
  79. try:
  80. connection.drain_events(timeout=2.0)
  81. except socket.timeout:
  82. pass
  83. except socket.error:
  84. if blueprint.state == RUN:
  85. raise