diff --git a/app/requirements.txt b/app/requirements.txt index 5bd1ce5..9d636fc 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -1,4 +1,4 @@ aiomqtt==2.3.2 schema==0.7.7 aiocron==2.1 - aiohttp==3.11.16 \ No newline at end of file + quart==0.20 \ No newline at end of file diff --git a/app/src/proxy.py b/app/src/proxy.py index 8c935f7..afb06f3 100644 --- a/app/src/proxy.py +++ b/app/src/proxy.py @@ -96,8 +96,8 @@ class Proxy(): Infos.new_stat_data[key] = False @classmethod - def class_close(cls, loop) -> None: # pragma: no cover + async def class_close(cls, loop) -> None: # pragma: no cover logging.debug('Proxy.class_close') logging.info('Close MQTT Task') - loop.run_until_complete(cls.mqtt.close()) + await cls.mqtt.close() cls.mqtt = None diff --git a/app/src/server.py b/app/src/server.py index 6056eb9..f78a38d 100644 --- a/app/src/server.py +++ b/app/src/server.py @@ -1,11 +1,10 @@ import logging import asyncio import logging.handlers -import signal import os import argparse from asyncio import StreamReader, StreamWriter -from aiohttp import web +from quart import Quart, Response from logging import config # noqa F401 from proxy import Proxy from inverter_ifc import InverterIfc @@ -18,28 +17,29 @@ from cnf.config_read_toml import ConfigReadToml from cnf.config_read_json import ConfigReadJson from modbus_tcp import ModbusTcp -routes = web.RouteTableDef() proxy_is_up = False - -@routes.get('/') -async def hello(request): - return web.Response(text="Hello, world") +app = Quart(__name__) -@routes.get('/-/ready') -async def ready(request): +@app.route('/') +async def hello(): + return Response(response="Hello, world") + + +@app.route('/-/ready') +async def ready(): if proxy_is_up: status = 200 text = 'Is ready' else: status = 503 text = 'Not ready' - return web.Response(status=status, text=text) + return Response(status=status, response=text) -@routes.get('/-/healthy') -async def healthy(request): +@app.route('/-/healthy') +async def healthy(): if proxy_is_up: # logging.info('web reqeust healthy()') @@ -47,32 +47,11 @@ async def healthy(request): try: res = inverter.healthy() if not res: - return web.Response(status=503, text="I have a problem") + return Response(status=503, response="I have a problem") except Exception as err: logging.info(f'Exception:{err}') - return web.Response(status=200, text="I'm fine") - - -async def webserver(addr, port): - '''coro running our webserver''' - app = web.Application() - app.add_routes(routes) - runner = web.AppRunner(app) - - await runner.setup() - site = web.TCPSite(runner, addr, port) - await site.start() - logging.info(f'HTTP server listen on port: {port}') - - try: - # Normal interaction with aiohttp - while True: - await asyncio.sleep(3600) # sleep forever - except asyncio.CancelledError: - logging.info('HTTP server cancelled') - await runner.cleanup() - logging.debug('HTTP cleanup done') + return Response(status=200, response="I'm fine") async def handle_client(reader: StreamReader, writer: StreamWriter, inv_class): @@ -82,10 +61,12 @@ async def handle_client(reader: StreamReader, writer: StreamWriter, inv_class): await inv.local.ifc.server_loop() -async def handle_shutdown(loop, web_task): +@app.after_serving +async def handle_shutdown(): '''Close all TCP connections and stop the event loop''' logging.info('Shutdown due to SIGTERM') + loop = asyncio.get_event_loop() global proxy_is_up proxy_is_up = False @@ -97,24 +78,16 @@ async def handle_shutdown(loop, web_task): logging.info('Proxy disconnecting done') - # - # second, cancel the web server - # - web_task.cancel() - await web_task - # # now cancel all remaining (pending) tasks # - pending = asyncio.all_tasks() - for task in pending: + for task in asyncio.all_tasks(): + if task == asyncio.current_task(): + continue task.cancel() + logging.info('Proxy cancelling done') - # - # at last, start a coro for stopping the loop - # - logging.debug("Stop event loop") - loop.stop() + await Proxy.class_close(loop) def get_log_level() -> int | None: @@ -214,27 +187,21 @@ def main(): # pragma: no cover loop.create_task(asyncio.start_server(lambda r, w, i=inv_class: handle_client(r, w, i), '0.0.0.0', port)) - web_task = loop.create_task(webserver('0.0.0.0', 8127)) - - # - # Register some UNIX Signal handler for a gracefully server shutdown - # on Docker restart and stop - # - for signame in ('SIGINT', 'SIGTERM'): - loop.add_signal_handler(getattr(signal, signame), - lambda loop=loop: asyncio.create_task( - handle_shutdown(loop, web_task))) loop.set_debug(log_level == logging.DEBUG) try: global proxy_is_up proxy_is_up = True - loop.run_forever() + logging.info("Start Quart") + app.run(host='0.0.0.0', port=8127, use_reloader=False, loop=loop) + logging.info("Quart stopped") + except KeyboardInterrupt: pass + except asyncio.exceptions.CancelledError: + logging.info("Quart cancelled") + finally: - logging.info("Event loop is stopped") - Proxy.class_close(loop) logging.debug('Close event loop') loop.close() logging.info(f'Finally, exit Server "{serv_name}"')