This repository has been archived by the owner on Dec 16, 2022. It is now read-only.
forked from Koed00/django-q
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updates the worker process to handle its own timeout, removing the ne…
…ed for some work in the guard loop. Also removes the double duty of timer as a timer and a status, status is now a dedicated enum
- Loading branch information
Showing
5 changed files
with
116 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
""" | ||
Using signal, implements a alarm based callback after a certain amount of time. | ||
Borrowed from rq: https://github.com/rq/rq/blob/master/rq/timeouts.py | ||
""" | ||
import signal | ||
|
||
|
||
class JobTimeoutException(Exception): | ||
"""Raised when a job takes longer to complete than the allowed maximum | ||
timeout value. | ||
""" | ||
pass | ||
|
||
|
||
class BaseDeathPenalty: | ||
"""Base class to setup job timeouts.""" | ||
|
||
def __init__(self, timeout, exception=JobTimeoutException, **kwargs): | ||
self._timeout = timeout | ||
self._exception = exception | ||
|
||
def __enter__(self): | ||
self.setup_death_penalty() | ||
|
||
def __exit__(self, type, value, traceback): | ||
# Always cancel immediately, since we're done | ||
try: | ||
self.cancel_death_penalty() | ||
except JobTimeoutException: | ||
# Weird case: we're done with the with body, but now the alarm is | ||
# fired. We may safely ignore this situation and consider the | ||
# body done. | ||
pass | ||
|
||
# __exit__ may return True to supress further exception handling. We | ||
# don't want to suppress any exceptions here, since all errors should | ||
# just pass through, BaseTimeoutException being handled normally to the | ||
# invoking context. | ||
return False | ||
|
||
def setup_death_penalty(self): | ||
raise NotImplementedError() | ||
|
||
def cancel_death_penalty(self): | ||
raise NotImplementedError() | ||
|
||
|
||
class UnixSignalDeathPenalty(BaseDeathPenalty): | ||
|
||
def handle_death_penalty(self, signum, frame): | ||
raise self._exception('Task exceeded maximum timeout value ' | ||
'({0} seconds)'.format(self._timeout)) | ||
|
||
def setup_death_penalty(self): | ||
"""Sets up an alarm signal and a signal handler that raises | ||
an exception after the timeout amount (expressed in seconds). | ||
""" | ||
signal.signal(signal.SIGALRM, self.handle_death_penalty) | ||
signal.alarm(self._timeout) | ||
|
||
def cancel_death_penalty(self): | ||
"""Removes the death penalty alarm and puts back the system into | ||
default signal handling. | ||
""" | ||
signal.alarm(0) | ||
signal.signal(signal.SIGALRM, signal.SIG_DFL) |