Trigger events

This commit is contained in:
messense 2017-03-12 22:42:34 +08:00
parent 19ee1dfecc
commit 2b296435b3
No known key found for this signature in database
GPG Key ID: BB41A8A2C716CCA9
4 changed files with 81 additions and 17 deletions

View File

@ -9,4 +9,5 @@ async def test(request):
return json({"test": True}) return json({"test": True})
app.run(host="0.0.0.0", port=8000) if __name__ == '__main__':
app.run(host="0.0.0.0", port=8000)

View File

@ -70,6 +70,11 @@ def query_string(request):
# Run Server # Run Server
# ----------------------------------------------- # # ----------------------------------------------- #
@app.listener('before_server_start')
def before_start(app, loop):
log.info("SERVER STARTING")
@app.listener('after_server_start') @app.listener('after_server_start')
def after_start(app, loop): def after_start(app, loop):
log.info("OH OH OH OH OHHHHHHHH") log.info("OH OH OH OH OHHHHHHHH")
@ -77,7 +82,13 @@ def after_start(app, loop):
@app.listener('before_server_stop') @app.listener('before_server_stop')
def before_stop(app, loop): def before_stop(app, loop):
log.info("SERVER STOPPING")
@app.listener('after_server_stop')
def after_stop(app, loop):
log.info("TRIED EVERYTHING") log.info("TRIED EVERYTHING")
app.run(host="0.0.0.0", port=8000, debug=True) if __name__ == '__main__':
app.run(host="0.0.0.0", port=8000, debug=True)

View File

@ -313,7 +313,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
after_start=None, before_stop=None, after_stop=None, debug=False, after_start=None, before_stop=None, after_stop=None, debug=False,
request_timeout=60, ssl=None, sock=None, request_max_size=None, request_timeout=60, ssl=None, sock=None, request_max_size=None,
reuse_port=False, loop=None, protocol=HttpProtocol, backlog=100, reuse_port=False, loop=None, protocol=HttpProtocol, backlog=100,
register_sys_signals=True, run_async=False): register_sys_signals=True, run_async=False, connections=None):
"""Start asynchronous HTTP Server on an individual process. """Start asynchronous HTTP Server on an individual process.
:param host: Address to host on :param host: Address to host on
@ -349,7 +349,7 @@ def serve(host, port, request_handler, error_handler, before_start=None,
trigger_events(before_start, loop) trigger_events(before_start, loop)
connections = set() connections = connections or set()
signal = Signal() signal = Signal()
server = partial( server = partial(
protocol, protocol,

View File

@ -1,16 +1,29 @@
import asyncio
import os import os
import asyncio
import logging
try:
import ssl
except ImportError:
ssl = None
import uvloop import uvloop
import gunicorn.workers.base as base import gunicorn.workers.base as base
from sanic.server import trigger_events, serve, HttpProtocol
from sanic.websocket import WebSocketProtocol
class GunicornWorker(base.Worker): class GunicornWorker(base.Worker):
def __init__(self, *args, **kw): # pragma: no cover def __init__(self, *args, **kw): # pragma: no cover
super().__init__(*args, **kw) super().__init__(*args, **kw)
cfg = self.cfg
if cfg.is_ssl:
self.ssl_context = self._create_ssl_context(cfg)
else:
self.ssl_context = None
self.servers = [] self.servers = []
self.connections = {} self.connections = set()
def init_process(self): def init_process(self):
# create new event_loop after fork # create new event_loop after fork
@ -28,20 +41,49 @@ class GunicornWorker(base.Worker):
try: try:
self.loop.run_until_complete(self._runner) self.loop.run_until_complete(self._runner)
finally: finally:
trigger_events(self._server_settings.get('before_stop', []), self.loop)
self.loop.close() self.loop.close()
trigger_events(self._server_settings.get('after_stop', []), self.loop)
async def close(self): async def close(self):
try: if self.servers:
if hasattr(self.wsgi, 'close'): # stop accepting connections
await self.wsgi.close() self.log.info("Stopping server: %s, connections: %s",
except: self.pid, len(self.connections))
self.log.exception('Process shutdown exception') for server in self.servers:
server.close()
await server.wait_closed()
self.servers.clear()
# prepare connections for closing
for conn in self.connections:
conn.close_if_idle()
while self.connections:
await asyncio.sleep(0.1)
async def _run(self): async def _run(self):
is_debug = self.log.loglevel == logging.DEBUG
protocol = (WebSocketProtocol if self.app.callable.websocket_enabled
else HttpProtocol)
self._server_settings = self.app.callable._helper(
host=None,
port=None,
loop=self.loop,
debug=is_debug,
protocol=protocol,
ssl=self.ssl_context,
run_async=True
)
self._server_settings.pop('sock')
for sock in self.sockets: for sock in self.sockets:
self.servers.append(await self.app.callable.create_server( self.servers.append(await serve(
sock=sock, host=None, port=None, loop=self.loop)) sock=sock,
connections=self.connections,
**self._server_settings
))
trigger_events(self._server_settings.get('after_start', []), self.loop)
# If our parent changed then we shut down. # If our parent changed then we shut down.
pid = os.getpid() pid = os.getpid()
try: try:
@ -56,8 +98,18 @@ class GunicornWorker(base.Worker):
except (Exception, BaseException, GeneratorExit, KeyboardInterrupt): except (Exception, BaseException, GeneratorExit, KeyboardInterrupt):
pass pass
if self.servers:
for server in self.servers:
server.close()
await self.close() await self.close()
@staticmethod
def _create_ssl_context(cfg):
""" Creates SSLContext instance for usage in asyncio.create_server.
See ssl.SSLSocket.__init__ for more details.
"""
ctx = ssl.SSLContext(cfg.ssl_version)
ctx.load_cert_chain(cfg.certfile, cfg.keyfile)
ctx.verify_mode = cfg.cert_reqs
if cfg.ca_certs:
ctx.load_verify_locations(cfg.ca_certs)
if cfg.ciphers:
ctx.set_ciphers(cfg.ciphers)
return ctx