Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement application events #173

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 33 additions & 12 deletions src/japronto/app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from japronto.router import Router, RouteNotFoundException
from japronto.protocol.cprotocol import Protocol
from japronto.protocol.creaper import Reaper

from japronto import helpers

signames = {
int(v): v.name for k, v in signal.__dict__.items()
Expand All @@ -31,6 +31,8 @@ def __init__(self, *, reaper_settings=None, log_request=None,
self._request_extensions = {}
self._protocol_factory = protocol_factory or Protocol
self._debug = debug
self._on_startup = []
self._on_cleanup = []

@property
def loop(self):
Expand All @@ -46,6 +48,14 @@ def router(self):

return self._router

@property
def on_startup(self):
return self._on_startup

@property
def on_cleanup(self):
return self._on_cleanup

def __finalize(self):
self.loop
self.router
Expand Down Expand Up @@ -163,28 +173,39 @@ def serve(self, *, sock, host, port, reloader_pid):
loop = self.loop
asyncio.set_event_loop(loop)

server_coro = loop.create_server(
lambda: self._protocol_factory(self), sock=sock)

server = loop.run_until_complete(server_coro)
for prepare in self.on_startup:
loop.run_until_complete(prepare(self))

loop.add_signal_handler(signal.SIGTERM, loop.stop)
loop.add_signal_handler(signal.SIGINT, loop.stop)
async def start_serving():
try:
server = await loop.create_server(
lambda: self._protocol_factory(self), sock=sock)
print('Accepting connections on http://{}:{}'.format(host, port))
while True:
await asyncio.sleep(3600)
except asyncio.CancelledError:
server.close()
await server.wait_closed()

def stop_serving():
for task in helpers.all_tasks(loop):
task.cancel()

loop.add_signal_handler(signal.SIGTERM, stop_serving)
loop.add_signal_handler(signal.SIGINT, stop_serving)

if reloader_pid:
from japronto.reloader import ChangeDetector
detector = ChangeDetector(loop)
detector.start()

print('Accepting connections on http://{}:{}'.format(host, port))

try:
loop.run_forever()
loop.run_until_complete(start_serving())
finally:
server.close()
loop.run_until_complete(server.wait_closed())
loop.run_until_complete(self.drain())
self._reaper.stop()
for finalize in self.on_cleanup:
loop.run_until_complete(finalize(self))
loop.close()

# break reference and cleanup matcher buffer
Expand Down
25 changes: 25 additions & 0 deletions src/japronto/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import sys
import asyncio
import types
import inspect

PY_37 = sys.version_info > (3, 7)
PY_38 = sys.version_info > (3, 8)

if PY_37:
all_tasks = asyncio.all_tasks
else:
def all_tasks(loop):
return set(filter(lambda t: not t.done(), asyncio.Task.all_tasks(loop)))

if PY_38:
def dismiss_coroutine(code):
return code.replace(co_flags=code.co_flags & ~inspect.CO_COROUTINE)
else:
def dismiss_coroutine(code):
return types.CodeType(
code.co_argcount, code.co_kwonlyargcount, code.co_nlocals, code.co_stacksize,
code.co_flags & ~inspect.CO_COROUTINE,
code.co_code, code.co_consts, code.co_names, code.co_varnames, code.co_filename,
code.co_name, code.co_firstlineno, code.co_lnotab, code.co_freevars,
code.co_cellvars)
10 changes: 2 additions & 8 deletions src/japronto/router/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import functools
import types


FLAG_COROUTINE = 128
from japronto import helpers


def is_simple(fun):
Expand Down Expand Up @@ -44,12 +43,7 @@ def coroutine_to_func(f):
# Based on http://stackoverflow.com/questions/13503079/
# how-to-create-a-copy-of-a-python-function
oc = f.__code__
code = types.CodeType(
oc.co_argcount, oc.co_kwonlyargcount, oc.co_nlocals, oc.co_stacksize,
oc.co_flags & ~FLAG_COROUTINE,
oc.co_code, oc.co_consts, oc.co_names, oc.co_varnames, oc.co_filename,
oc.co_name, oc.co_firstlineno, oc.co_lnotab, oc.co_freevars,
oc.co_cellvars)
code = helpers.dismiss_coroutine(oc)
g = types.FunctionType(
code, f.__globals__, name=f.__name__, argdefs=f.__defaults__,
closure=f.__closure__)
Expand Down