|
|
|
@ -323,47 +323,47 @@ class Worker(object):
|
|
|
|
|
gracefully.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def request_force_stop(signum, frame):
|
|
|
|
|
"""Terminates the application (cold shutdown).
|
|
|
|
|
"""
|
|
|
|
|
self.log.warning('Cold shut down')
|
|
|
|
|
|
|
|
|
|
# Take down the horse with the worker
|
|
|
|
|
if self.horse_pid:
|
|
|
|
|
msg = 'Taking down horse {0} with me'.format(self.horse_pid)
|
|
|
|
|
self.log.debug(msg)
|
|
|
|
|
try:
|
|
|
|
|
os.kill(self.horse_pid, signal.SIGKILL)
|
|
|
|
|
except OSError as e:
|
|
|
|
|
# ESRCH ("No such process") is fine with us
|
|
|
|
|
if e.errno != errno.ESRCH:
|
|
|
|
|
self.log.debug('Horse already down')
|
|
|
|
|
raise
|
|
|
|
|
raise SystemExit()
|
|
|
|
|
signal.signal(signal.SIGINT, self.request_stop)
|
|
|
|
|
signal.signal(signal.SIGTERM, self.request_stop)
|
|
|
|
|
|
|
|
|
|
def request_stop(signum, frame):
|
|
|
|
|
"""Stops the current worker loop but waits for child processes to
|
|
|
|
|
end gracefully (warm shutdown).
|
|
|
|
|
"""
|
|
|
|
|
self.log.debug('Got signal {0}'.format(signal_name(signum)))
|
|
|
|
|
def request_force_stop(self, signum, frame):
|
|
|
|
|
"""Terminates the application (cold shutdown).
|
|
|
|
|
"""
|
|
|
|
|
self.log.warning('Cold shut down')
|
|
|
|
|
|
|
|
|
|
signal.signal(signal.SIGINT, request_force_stop)
|
|
|
|
|
signal.signal(signal.SIGTERM, request_force_stop)
|
|
|
|
|
# Take down the horse with the worker
|
|
|
|
|
if self.horse_pid:
|
|
|
|
|
msg = 'Taking down horse {0} with me'.format(self.horse_pid)
|
|
|
|
|
self.log.debug(msg)
|
|
|
|
|
try:
|
|
|
|
|
os.kill(self.horse_pid, signal.SIGKILL)
|
|
|
|
|
except OSError as e:
|
|
|
|
|
# ESRCH ("No such process") is fine with us
|
|
|
|
|
if e.errno != errno.ESRCH:
|
|
|
|
|
self.log.debug('Horse already down')
|
|
|
|
|
raise
|
|
|
|
|
raise SystemExit()
|
|
|
|
|
|
|
|
|
|
def request_stop(self, signum, frame):
|
|
|
|
|
"""Stops the current worker loop but waits for child processes to
|
|
|
|
|
end gracefully (warm shutdown).
|
|
|
|
|
"""
|
|
|
|
|
self.log.debug('Got signal {0}'.format(signal_name(signum)))
|
|
|
|
|
|
|
|
|
|
msg = 'Warm shut down requested'
|
|
|
|
|
self.log.warning(msg)
|
|
|
|
|
signal.signal(signal.SIGINT, self.request_force_stop)
|
|
|
|
|
signal.signal(signal.SIGTERM, self.request_force_stop)
|
|
|
|
|
|
|
|
|
|
# If shutdown is requested in the middle of a job, wait until
|
|
|
|
|
# finish before shutting down
|
|
|
|
|
if self.get_state() == 'busy':
|
|
|
|
|
self._stop_requested = True
|
|
|
|
|
self.log.debug('Stopping after current horse is finished. '
|
|
|
|
|
'Press Ctrl+C again for a cold shutdown.')
|
|
|
|
|
else:
|
|
|
|
|
raise StopRequested()
|
|
|
|
|
msg = 'Warm shut down requested'
|
|
|
|
|
self.log.warning(msg)
|
|
|
|
|
|
|
|
|
|
signal.signal(signal.SIGINT, request_stop)
|
|
|
|
|
signal.signal(signal.SIGTERM, request_stop)
|
|
|
|
|
# If shutdown is requested in the middle of a job, wait until
|
|
|
|
|
# finish before shutting down
|
|
|
|
|
if self.get_state() == 'busy':
|
|
|
|
|
self._stop_requested = True
|
|
|
|
|
self.log.debug('Stopping after current horse is finished. '
|
|
|
|
|
'Press Ctrl+C again for a cold shutdown.')
|
|
|
|
|
else:
|
|
|
|
|
raise StopRequested()
|
|
|
|
|
|
|
|
|
|
def check_for_suspension(self, burst):
|
|
|
|
|
"""Check to see if workers have been suspended by `rq suspend`"""
|
|
|
|
@ -491,9 +491,10 @@ class Worker(object):
|
|
|
|
|
within the given timeout bounds, or will end the work horse with
|
|
|
|
|
SIGALRM.
|
|
|
|
|
"""
|
|
|
|
|
self.set_state('busy')
|
|
|
|
|
child_pid = os.fork()
|
|
|
|
|
os.environ['RQ_WORKER_ID'] = self.name
|
|
|
|
|
os.environ['RQ_JOB_ID'] = job.id
|
|
|
|
|
child_pid = os.fork()
|
|
|
|
|
if child_pid == 0:
|
|
|
|
|
self.main_work_horse(job)
|
|
|
|
|
else:
|
|
|
|
@ -501,7 +502,6 @@ class Worker(object):
|
|
|
|
|
self.procline('Forked {0} at {0}'.format(child_pid, time.time()))
|
|
|
|
|
while True:
|
|
|
|
|
try:
|
|
|
|
|
self.set_state('busy')
|
|
|
|
|
os.waitpid(child_pid, 0)
|
|
|
|
|
self.set_state('idle')
|
|
|
|
|
break
|
|
|
|
@ -601,10 +601,10 @@ class Worker(object):
|
|
|
|
|
self.handle_exception(job, *sys.exc_info())
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if rv is None:
|
|
|
|
|
self.log.info('Job OK')
|
|
|
|
|
else:
|
|
|
|
|
self.log.info('Job OK, result = {0!r}'.format(yellow(text_type(rv))))
|
|
|
|
|
self.log.info('{0}: {1} ({2})'.format(green(job.origin), blue('Job OK'), job.id))
|
|
|
|
|
if rv:
|
|
|
|
|
log_result = "{0!r}".format(as_text(text_type(rv)))
|
|
|
|
|
self.log.debug('Result: {0}'.format(yellow(log_result)))
|
|
|
|
|
|
|
|
|
|
if result_ttl == 0:
|
|
|
|
|
self.log.info('Result discarded immediately')
|
|
|
|
@ -665,6 +665,7 @@ class Worker(object):
|
|
|
|
|
def clean_registries(self):
|
|
|
|
|
"""Runs maintenance jobs on each Queue's registries."""
|
|
|
|
|
for queue in self.queues:
|
|
|
|
|
self.log.info('Cleaning registries for queue: {0}'.format(queue.name))
|
|
|
|
|
clean_registries(queue)
|
|
|
|
|
self.last_cleaned_at = utcnow()
|
|
|
|
|
|
|
|
|
|