Skip to content

Instantly share code, notes, and snippets.

@proteneer
Last active August 29, 2015 14:01
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 proteneer/a1bd29592809e1457f8d to your computer and use it in GitHub Desktop.
Save proteneer/a1bd29592809e1457f8d to your computer and use it in GitHub Desktop.
tornado + redis
import tornado.web
import tornado.httpserver
import tornado.ioloop
import process2
import tornado.netutil
import redis
import signal
import time
import sys
import os
import subprocess
def preexec(): # Don't forward signals.
os.setpgrp()
def init_redis(redis_options, cwd=None):
""" Spawn a redis subprocess port and returns a redis client. """
print("Creating redis subprocess on ", process2.task_id())
redis_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'..', 'redis', 'src', 'redis-server')
redis_path = os.path.abspath(redis_path)
args = [redis_path]
for option_name, option_value in redis_options.items():
args.append('--'+option_name)
args.append(str(option_value))
redis_process = subprocess.Popen(args, cwd=cwd, preexec_fn=preexec)
if redis_process.poll() is not None:
print('Could not start redis server, aborting')
sys.exit(0)
redis_port = redis_options['port']
redis_client = redis.Redis(host='localhost', port=int(redis_port),
decode_responses=True)
# poll until redis server is alive
alive = False
start_time = time.time()
while time.time()-start_time < 15.0:
try:
alive = redis_client.ping()
break
except Exception:
pass
if not alive:
raise ValueError('Could not start redis')
return redis_client
class ExampleApp(tornado.web.Application):
def __init__(self, db):
self.db = db
super(ExampleApp, self).__init__([])
def shutdown(self):
tornado.ioloop.IOLoop.instance().stop()
def stop_parent(sig, frame):
pass
def stop_children(sig, frame):
print('-> stopping children', process2.task_id())
# stop accepting new requests
server.stop()
# wait for all the locks to expire
deadline = time.time() + 10
io_loop = tornado.ioloop.IOLoop.instance()
def stop_loop():
now = time.time()
if now < deadline and app.db.zrange('locks', 0, -1):
io_loop.add_timeout(now + 1, stop_loop)
else:
app.shutdown()
stop_loop()
def start():
redis_options = {
'port': 2873,
'appendfilename': 'redis.aof',
'logfile': 'redis.log',
}
db = init_redis(redis_options)
global app
app = ExampleApp(db)
global server
sockets = tornado.netutil.bind_sockets(9873)
# forces parent to ignore Ctrl-C exits
signal.signal(signal.SIGINT, stop_parent)
signal.signal(signal.SIGTERM, stop_parent)
try:
process2.fork_processes(0)
signal.signal(signal.SIGINT, stop_children)
signal.signal(signal.SIGTERM, stop_children)
server = tornado.httpserver.HTTPServer(app)
server.add_sockets(sockets)
tornado.ioloop.IOLoop.instance().start()
except SystemExit as e:
print('parent is shutting down ...', e)
app.db.shutdown()
sys.exit(0)
start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment