|
13 | 13 | current_task,
|
14 | 14 | gather,
|
15 | 15 | get_event_loop,
|
| 16 | + set_event_loop_policy, |
16 | 17 | wait,
|
17 | 18 | )
|
| 19 | +from contextlib import suppress |
| 20 | +from signal import SIGHUP, SIGINT, SIGTERM |
18 | 21 | from typing import TypedDict, cast
|
19 | 22 |
|
20 | 23 | from dependency_injector.wiring import register_loader_containers
|
|
36 | 39 | except ImportError:
|
37 | 40 | from tomli import loads # type: ignore[no-redef,import-not-found,unused-ignore]
|
38 | 41 |
|
39 |
| -try: |
40 |
| - from uvloop import run # type: ignore[import-not-found,unused-ignore] |
41 |
| -except ImportError: |
42 |
| - from asyncio import run # type: ignore[no-redef,assignment,unused-ignore] |
43 |
| - |
44 | 42 |
|
45 | 43 | class PyFSDDatabaseConfig(TypedDict):
|
46 | 44 | """PyFSD database config.
|
@@ -165,8 +163,10 @@ async def launch(config: RootPyFSDConfig, *, wait_all_tasks_done: bool = True) -
|
165 | 163 | raise
|
166 | 164 |
|
167 | 165 |
|
| 166 | +# ruff: noqa: C901 |
168 | 167 | def main() -> None:
|
169 | 168 | """Main function of PyFSD."""
|
| 169 | + # =============== Config |
170 | 170 | parser = ArgumentParser()
|
171 | 171 | parser.add_argument(
|
172 | 172 | "-c",
|
@@ -208,10 +208,37 @@ def main() -> None:
|
208 | 208 | # else we have nothing to do :)
|
209 | 209 | config["pyfsd"]["database"]["url"] = db_url
|
210 | 210 |
|
| 211 | + # =============== Logger |
211 | 212 | suppress_metar_parser_warning()
|
212 | 213 | setup_logger(config["pyfsd"]["logger"])
|
213 |
| - try: |
214 |
| - run(launch(cast("RootPyFSDConfig", config))) |
215 |
| - finally: |
216 |
| - # Ensure we have working loggers when cpython is shutting down |
217 |
| - setup_logger(config["pyfsd"]["logger"], finalize=True) |
| 214 | + |
| 215 | + # =============== Startup |
| 216 | + with suppress(ImportError): |
| 217 | + from uvloop import EventLoopPolicy |
| 218 | + |
| 219 | + set_event_loop_policy(EventLoopPolicy()) |
| 220 | + |
| 221 | + loop = get_event_loop() |
| 222 | + |
| 223 | + async def runner() -> None: |
| 224 | + try: |
| 225 | + await launch(cast("RootPyFSDConfig", config)) |
| 226 | + except CancelledError: |
| 227 | + pass |
| 228 | + except BaseException: |
| 229 | + logger.exception("Error happened when launching PyFSD") |
| 230 | + |
| 231 | + await loop.shutdown_asyncgens() |
| 232 | + await loop.shutdown_default_executor() |
| 233 | + loop.stop() |
| 234 | + |
| 235 | + runner_task = loop.create_task(runner()) |
| 236 | + |
| 237 | + for signal in [SIGINT, SIGTERM, SIGHUP]: |
| 238 | + loop.add_signal_handler(signal, runner_task.cancel) |
| 239 | + loop.run_forever() # complete after loop.stop() |
| 240 | + |
| 241 | + # =============== Stop |
| 242 | + loop.close() |
| 243 | + # Ensure we have working loggers when cpython is shutting down |
| 244 | + setup_logger(config["pyfsd"]["logger"], finalize=True) |
0 commit comments