From 16009b9bba1432f14eeb689f6bfcca4985d5a7bd Mon Sep 17 00:00:00 2001 From: GabrielBarberini Date: Mon, 29 Apr 2024 22:30:05 -0300 Subject: [PATCH] fixes async issues --- lib/__init__.py | 8 +++ lib/api.py | 7 ++- lib/controllers/environment.py | 105 ++++++++++++++------------------ lib/repositories/environment.py | 61 ++++++++----------- lib/repositories/repo.py | 5 +- 5 files changed, 84 insertions(+), 102 deletions(-) diff --git a/lib/__init__.py b/lib/__init__.py index a1bcc92..b328917 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,2 +1,10 @@ # lib/__init__.py +import logging from .api import app + +logging.basicConfig( + level=logging.INFO, + filename='app.log', + filemode='a', + format='%(asctime)s - %(levelname)s - %(message)s', +) diff --git a/lib/api.py b/lib/api.py index 01632a6..6896bed 100644 --- a/lib/api.py +++ b/lib/api.py @@ -2,16 +2,17 @@ This is the main API file for the RocketPy API. """ -import logging - from fastapi import FastAPI, Request, status from fastapi.exceptions import RequestValidationError from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.utils import get_openapi from fastapi.responses import RedirectResponse, JSONResponse +from lib import logging from lib.routes import flight, environment, motor, rocket +logger = logging.getLogger(__name__) + app = FastAPI( swagger_ui_parameters={ "defaultModelsExpandDepth": 0, @@ -84,7 +85,7 @@ async def validation_exception_handler( request: Request, exc: RequestValidationError ): exc_str = f"{exc}".replace("\n", " ").replace(" ", " ") - logging.error(f"{request}: {exc_str}") + logger.error(f"{request}: {exc_str}") content = {"status_code": 10422, "message": exc_str, "data": None} return JSONResponse( content=content, status_code=status.HTTP_422_UNPROCESSABLE_ENTITY diff --git a/lib/controllers/environment.py b/lib/controllers/environment.py index f11d8c6..fc3b6f7 100644 --- a/lib/controllers/environment.py +++ b/lib/controllers/environment.py @@ -1,11 +1,10 @@ from typing import Union -from datetime import datetime -import logging import jsonpickle from rocketpy.environment.environment import Environment as RocketPyEnvironment from fastapi import HTTPException, status +from lib import logging from lib.controllers import parse_error from lib.models.environment import Env from lib.repositories.environment import EnvRepository @@ -19,6 +18,8 @@ EnvPickle, ) +logger = logging.getLogger(__name__) + class EnvController: """ @@ -69,23 +70,22 @@ async def create_env(self) -> "Union[EnvCreated, HTTPException]": Returns: views.EnvCreated """ - env_repo = EnvRepository(environment=self.env) try: - await env_repo.create_env() + created_env = await EnvRepository( + environment=self.env + ).create_env() except Exception as e: exc_str = parse_error(e) - logging.error( - f"[{datetime.now()}] controllers.environment.create_env: {exc_str}" - ) + logger.error(f"controllers.environment.create_env: {exc_str}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to create environment: {e}", ) from e else: - return EnvCreated(env_id=env_repo.env_id) + return EnvCreated(env_id=created_env.env_id) finally: - logging.info( - f"[{datetime.now()}] Call to controllers.environment.create_env completed; params: Env {hash(self.env)}" + logger.info( + f"Call to controllers.environment.create_env completed; params: Env {hash(self.env)}" ) @staticmethod @@ -102,14 +102,11 @@ async def get_env_by_id(env_id: int) -> "Union[Env, HTTPException]": Raises: HTTP 404 Not Found: If the env is not found in the database. """ - env_repo = EnvRepository(env_id=env_id) try: - read_env = await env_repo.get_env() + read_env = await EnvRepository(env_id=env_id).get_env() except Exception as e: exc_str = parse_error(e) - logging.error( - f"[{datetime.now()}] controllers.environment.get_env_by_id: {exc_str}" - ) + logger.error(f"controllers.environment.get_env_by_id: {exc_str}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to read environment: {e}", @@ -122,8 +119,8 @@ async def get_env_by_id(env_id: int) -> "Union[Env, HTTPException]": detail="Environment not found", ) finally: - logging.info( - f"[{datetime.now()}] Call to controllers.environment.get_env_by_id completed; params: EnvID {env_id}" + logger.info( + f"Call to controllers.environment.get_env_by_id completed; params: EnvID {env_id}" ) @classmethod @@ -143,31 +140,27 @@ async def get_rocketpy_env_as_jsonpickle( Raises: HTTP 404 Not Found: If the env is not found in the database. """ - env_repo = EnvRepository(env_id=env_id) try: - read_env = await env_repo.get_env() + read_env = await cls.get_env_by_id(env_id) + except HTTPException as e: + raise e from e except Exception as e: exc_str = parse_error(e) - logging.error( - f"[{datetime.now()}] controllers.environment.get_rocketpy_env_as_jsonpickle: {exc_str}" + logger.error( + f"controllers.environment.get_rocketpy_env_as_jsonpickle: {exc_str}" ) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to read environment: {e}", ) from e else: - if read_env: - rocketpy_env = cls.get_rocketpy_env(read_env) - return EnvPickle( - jsonpickle_rocketpy_env=jsonpickle.encode(rocketpy_env) - ) - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail="Environment not found", + rocketpy_env = await cls.get_rocketpy_env(read_env) + return EnvPickle( + jsonpickle_rocketpy_env=jsonpickle.encode(rocketpy_env) ) finally: - logging.info( - f"[{datetime.now()}] Call to controllers.environment.get_rocketpy_env_as_jsonpickle completed; params: EnvID {env_id}" + logger.info( + f"Call to controllers.environment.get_rocketpy_env_as_jsonpickle completed; params: EnvID {env_id}" ) async def update_env( @@ -185,30 +178,25 @@ async def update_env( Raises: HTTP 404 Not Found: If the env is not found in the database. """ - env_repo = EnvRepository(environment=self.env, env_id=env_id) try: - read_env = await env_repo.get_env() - if read_env: - await env_repo.update_env() - else: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail="Environment not found", - ) + await EnvController.get_env_by_id(env_id) + updated_env = await EnvRepository( + environment=self.env, env_id=env_id + ).update_env() + except HTTPException as e: + raise e from e except Exception as e: exc_str = parse_error(e) - logging.error( - f"[{datetime.now()}] controllers.environment.update_env: {exc_str}" - ) + logger.error(f"controllers.environment.update_env: {exc_str}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to update environment: {e}", ) from e else: - return EnvUpdated(new_env_id=env_repo.env_id) + return EnvUpdated(new_env_id=updated_env.env_id) finally: - logging.info( - f"[{datetime.now()}] Call to controllers.environment.update_env completed; params: EnvID {env_id}, Env {hash(self.env)}" + logger.info( + f"Call to controllers.environment.update_env completed; params: EnvID {env_id}, Env {hash(self.env)}" ) @staticmethod @@ -225,14 +213,11 @@ async def delete_env(env_id: str) -> "Union[EnvDeleted, HTTPException]": Raises: HTTP 404 Not Found: If the env is not found in the database. """ - env_repo = EnvRepository(env_id=env_id) try: - await env_repo.delete_env() + await EnvRepository(env_id=env_id).delete_env() except Exception as e: exc_str = parse_error(e) - logging.error( - f"[{datetime.now()}] controllers.environment.delete_env: {exc_str}" - ) + logger.error(f"controllers.environment.delete_env: {exc_str}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to delete environment: {e}", @@ -240,8 +225,8 @@ async def delete_env(env_id: str) -> "Union[EnvDeleted, HTTPException]": else: return EnvDeleted(deleted_env_id=env_id) finally: - logging.info( - f"[{datetime.now()}] Call to controllers.environment.delete_env completed; params: EnvID {env_id}" + logger.info( + f"Call to controllers.environment.delete_env completed; params: EnvID {env_id}" ) @classmethod @@ -258,9 +243,9 @@ async def simulate(cls, env_id: int) -> "Union[EnvSummary, HTTPException]": Raises: HTTP 404 Not Found: If the env does not exist in the database. """ - read_env = await cls.get_env_by_id(env_id) try: - rocketpy_env = cls.get_rocketpy_env(read_env) + read_env = await cls.get_env_by_id(env_id) + rocketpy_env = await cls.get_rocketpy_env(read_env) env_simulation_numbers = EnvData.parse_obj( rocketpy_env.all_info_returned() ) @@ -270,11 +255,11 @@ async def simulate(cls, env_id: int) -> "Union[EnvSummary, HTTPException]": env_summary = EnvSummary( env_data=env_simulation_numbers, env_plots=env_simulation_plots ) + except HTTPException as e: + raise e from e except Exception as e: exc_str = parse_error(e) - logging.error( - f"[{datetime.now()}] controllers.environment.simulate: {exc_str}" - ) + logger.error(f"controllers.environment.simulate: {exc_str}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to simulate environment: {e}", @@ -282,6 +267,6 @@ async def simulate(cls, env_id: int) -> "Union[EnvSummary, HTTPException]": else: return env_summary finally: - logging.info( - f"[{datetime.now()}] Call to controllers.environment.simulate completed; params: EnvID {env_id}" + logger.info( + f"Call to controllers.environment.simulate completed; params: EnvID {env_id}" ) diff --git a/lib/repositories/environment.py b/lib/repositories/environment.py index 53a1ea7..e0d56bf 100644 --- a/lib/repositories/environment.py +++ b/lib/repositories/environment.py @@ -1,10 +1,11 @@ -import logging -from datetime import datetime from typing import Union +from lib import logging from lib.repositories import parse_error from lib.models.environment import Env from lib.repositories.repo import Repository +logger = logging.getLogger(__name__) + class EnvRepository(Repository): """ @@ -22,7 +23,7 @@ def __init__(self, environment: Env = None, env_id: str = None): if env_id: self._env_id = env_id else: - self._env_id = hash(self._env) + self._env_id = str(hash(self._env)) @property def env(self) -> "Env": @@ -45,55 +46,49 @@ async def create_env(self): Creates a non-existing models.Env in the database Returns: - None + self """ - env_exists = await self.get_env() - if env_exists: - return - try: environment_to_dict = self.env.dict() environment_to_dict["env_id"] = self.env_id await self.collection.insert_one(environment_to_dict) except Exception as e: exc_str = parse_error(e) - logging.error( - f"[{datetime.now()}] repositories.environment.create_env: {exc_str}" - ) + logger.error(f"repositories.environment.create_env: {exc_str}") raise Exception(f"Error creating environment: {str(e)}") from e + else: + return self finally: - logging.info( - f"[{datetime.now()}] Call to repositories.environment.create_env completed; states: Env {hash(self.env)}, EnvID {self.env_id}" + logger.info( + f"Call to repositories.environment.create_env completed; states: EnvID {self.env_id}" ) - self.close_connection() + await self.close_connection() async def update_env(self): """ Updates a models.Env in the database Returns: - None + self """ try: environment_to_dict = self.env.dict() - environment_to_dict["env_id"] = hash(self.env) + environment_to_dict["env_id"] = str(hash(self.env)) await self.collection.update_one( {"env_id": self.env_id}, {"$set": environment_to_dict} ) self.env_id = environment_to_dict["env_id"] except Exception as e: exc_str = parse_error(e) - logging.error( - f"[{datetime.now()}] repositories.environment.update_env: {exc_str}" - ) + logger.error(f"repositories.environment.update_env: {exc_str}") raise Exception(f"Error updating environment: {str(e)}") from e else: - return + return self finally: - logging.info( - f"[{datetime.now()}] Call to repositories.environment.update_env completed; states: Env {hash(self.env)}, EnvID {self.env_id}" + logger.info( + f"Call to repositories.environment.update_env completed; states: Env {hash(self.env)}, EnvID {self.env_id}" ) - self.close_connection() + await self.close_connection() async def get_env(self) -> "Union[Env, None]": """ @@ -105,17 +100,15 @@ async def get_env(self) -> "Union[Env, None]": try: read_env = await self.collection.find_one({"env_id": self.env_id}) except Exception as e: - logging.error( - f"[{datetime.now()}] repositories.environment.get_env: {str(e)}" - ) + logger.error(f"repositories.environment.get_env: {str(e)}") raise Exception(f"Error getting environment: {str(e)}") from e else: return Env.parse_obj(read_env) if read_env else None finally: - logging.info( - f"[{datetime.now()}] Call to repositories.environment.get_env completed; states: Env {hash(self.env)}, EnvID {self.env_id}" + logger.info( + f"Call to repositories.environment.get_env completed; states: Env {hash(self.env)}, EnvID {self.env_id}" ) - self.close_connection() + await self.close_connection() async def delete_env(self): """ @@ -127,12 +120,10 @@ async def delete_env(self): try: await self.collection.delete_one({"env_id": self.env_id}) except Exception as e: - logging.error( - f"[{datetime.now()}] repositories.environment.delete_env: {str(e)}" - ) + logger.error(f"repositories.environment.delete_env: {str(e)}") raise Exception(f"Error deleting environment: {str(e)}") from e finally: - logging.info( - f"[{datetime.now()}] Call to repositories.environment.delete_env completed; states: Env {hash(self.env)}, EnvID {self.env_id}" + logger.info( + f"Call to repositories.environment.delete_env completed; states: Env {hash(self.env)}, EnvID {self.env_id}" ) - self.close_connection() + await self.close_connection() diff --git a/lib/repositories/repo.py b/lib/repositories/repo.py index d72e74a..1c3028d 100644 --- a/lib/repositories/repo.py +++ b/lib/repositories/repo.py @@ -1,5 +1,3 @@ -import logging -from datetime import datetime from motor.motor_asyncio import AsyncIOMotorClient from pymongo.server_api import ServerApi from lib.secrets import secrets_instance @@ -27,6 +25,5 @@ def __init__(self, collection: str): self.db = self.client.rocketpy self.collection = self.db[collection] - def close_connection(self) -> None: - logging.info(f"[{datetime.now()}] Closing connection to database") + async def close_connection(self) -> None: self.client.close()