1
0
mirror of https://github.com/ijaric/voice_assistant.git synced 2025-05-24 14:33:26 +00:00
voice_assistant/src/python-service/lib/app/app.py
2023-09-19 17:16:30 +03:00

135 lines
3.6 KiB
Python

import asyncio
import dataclasses
import logging
import typing
import aiohttp.web as aiohttp_web
import lib.api.rest.v1.health as health_handlers
import lib.app.errors as app_errors
import lib.app.settings as app_settings
import typing_extensions
logger = logging.getLogger(__name__)
@dataclasses.dataclass
class DisposableResource:
name: str
dispose_callback: typing.Awaitable[typing.Any]
class Application:
def __init__(
self,
settings: app_settings.Settings,
aio_app: aiohttp_web.Application,
disposable_resources: typing.Sequence[DisposableResource],
) -> None:
self._settings = settings
self._aio_app = aio_app
self._disposable_resources = disposable_resources
@classmethod
def from_settings(cls, settings: app_settings.Settings) -> typing_extensions.Self:
# Logging
logging.basicConfig(
level=settings.LOGS_MIN_LEVEL,
format=settings.LOGS_FORMAT,
)
logger.info("Initializing application")
disposable_resources = []
# Global clients
logger.info("Initializing global clients")
# Clients
logger.info("Initializing clients")
# Repositories
logger.info("Initializing repositories")
# Caches
logger.info("Initializing caches")
# Services
logger.info("Initializing services")
# Handlers
logger.info("Initializing handlers")
liveness_probe_handler = health_handlers.LivenessProbeHandler()
logger.info("Creating application")
aio_app = aiohttp_web.Application()
# Routes
aio_app.add_routes(
[
aiohttp_web.get(
"/api/v1/health/liveness",
liveness_probe_handler.process,
),
]
)
application = Application(
settings=settings,
aio_app=aio_app,
disposable_resources=disposable_resources,
)
logger.info("Initializing application finished")
return application
async def start(self) -> None:
logger.info("Discord server is starting")
try:
await aiohttp_web._run_app(
app=self._aio_app,
host=self._settings.SERVER_HOST,
port=self._settings.SERVER_PORT,
)
except asyncio.CancelledError:
logger.info("HTTP server has been interrupted")
except BaseException as unexpected_error:
logger.exception("HTTP server failed to start")
raise app_errors.StartServerError(
"HTTP server failed to start"
) from unexpected_error
async def dispose(self) -> None:
logger.info("Application is shutting down...")
dispose_errors = []
for resource in self._disposable_resources:
logger.info("Disposing %s...", resource.name)
try:
await resource.dispose_callback
except Exception as unexpected_error:
dispose_errors.append(unexpected_error)
logger.exception("Failed to dispose %s", resource.name)
else:
logger.info("%s has been disposed", resource.name)
if len(dispose_errors) != 0:
logger.error("Application has shut down with errors")
raise app_errors.DisposeError(
"Application has shut down with errors, see logs above"
)
logger.info("Application has successfully shut down")
__all__ = [
"Application",
]