Skip to content

Instantly share code, notes, and snippets.

@CrazyPython
Last active December 6, 2022 22:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CrazyPython/15045a2f73d8368648c1 to your computer and use it in GitHub Desktop.
Save CrazyPython/15045a2f73d8368648c1 to your computer and use it in GitHub Desktop.

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
_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
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')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment