Shutdown middleware for django on Heroku. See http://stackoverflow.com/questions/30969597/how-do-i-handle-dyno-restarts-when-using-django/31031867#31031867 for more details.
from django.http import HttpResponse
_current_shutdown_middleware = None
# Used in situations where it must shutdown before it gets initialized
_pre_shutdown = False
class ShutdownMiddleware(object):
shutting_down = False
def __init__(self):
_current_shutdown_middleware = self
if _pre_shutdown:
self.shutting_down = True
@staticmethod
def shutdown_switch():
"""Activate the shutdown switch"""
self = current_shutdown_middleware
try:
self.shutting_down = True
except AttributeError:
# Has not processed first request, requesting shutdown
sys.stderr.write('[ShutdownMiddleware.shutdown_switch] Requested Shutdown, not yet initialized.\n')
_pre_shutdown = True
def process_request(self, request):
if self.shutting_down:
return HttpResponse('500 internal server error\n'
'Server restarting; please try again in 10 seconds.\n', status=500, content_type='text/plain')
else:
return None
Hello! I created this gist to demonstrate how you can handle Heroku dyno restarts in Django. This is based off of this stackoverflow question. Many thanks to the writer of the awnser. To put activate the Middleware, you must put this in your django settings file:
MIDDLEWARE_CLASSES = (
'Middleware.ShutdownMiddleware',
# All the prexisting classes
...
)
You should probably put this at the top so you can return the 500 error instantly, but if you have something like SSLify you may want to put that at the top, but it puts a small barrier between you and the instant server-wide 500 error. That's it!
Thanks to everybody mentioned on the stackoverflow question, including the OP.
Bye! ~CrazyPython
from django.http import HttpResponse
from Middleware import ShutdownMiddleware
import signal
import sys
class TerminationManager(object):
def __init__(self):
self._running = True
signal.signal(signal.SIGTERM, self._start_shutdown)
def _start_shutdown(self, signum, stack):
sys.stderr.write('[TerminationManager] Recieved SIGTERM. Stopping new requests.')
self._running = False
ShutdownMiddleware.shutdown_switch()
termination_manager = TerminationManager()
def dummy_view(request):
return HttpResponse('Hello! I am a dummy.', content_type='text/plain')