From a400ea2cc25302c92f89b002d20da3e02257eea1 Mon Sep 17 00:00:00 2001 From: Prisha Patel <19prishpat@gmail.com> Date: Tue, 6 May 2025 13:16:05 -0400 Subject: [PATCH 1/2] Backend Onboarding --- backend/api/endpoints/command.py | 16 +++++++++++++-- backend/api/middlewares/logger_middleware.py | 21 ++++++++++++++++++++ backend/data/data_models.py | 16 ++++++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/backend/api/endpoints/command.py b/backend/api/endpoints/command.py index 583ea5a..bf97a7b 100644 --- a/backend/api/endpoints/command.py +++ b/backend/api/endpoints/command.py @@ -24,7 +24,7 @@ def get_commands(db: Session = Depends(get_db)): @command_router.post("/", response_model=CommandSingleResponse) -def create_command(payload: CommandRequest): +def create_command(payload: CommandRequest, db: Session = Depends(get_db)): """ Creates an item with the given payload in the database and returns this payload after pulling it from the database @@ -32,11 +32,16 @@ def create_command(payload: CommandRequest): @return returns a json object with field of "data" under which there is the payload now pulled from the database """ # TODO:(Member) Implement this endpoint + command = Command(**payload.model_dump()) + db.add(command) + db.commit() + db.refresh(command) + return {"data": command} @command_router.delete("/{id}", response_model=CommandListResponse) -def delete_command(id: int): +def delete_command(id: int, db: Session = Depends(get_db)): """ Deletes the item with the given id if it exists. Otherwise raises a 404 error. @@ -44,3 +49,10 @@ def delete_command(id: int): @return returns the list of commands after deleting the item """ # TODO:(Member) Implement this endpoint + command = db.get(Command, id) + if not command: + raise HTTPException(status_code=404, detail="Command not found") + db.delete(command) + db.commit() + items = db.exec(select(Command)).all() + return {"data": items} \ No newline at end of file diff --git a/backend/api/middlewares/logger_middleware.py b/backend/api/middlewares/logger_middleware.py index 44daa5d..460ce02 100644 --- a/backend/api/middlewares/logger_middleware.py +++ b/backend/api/middlewares/logger_middleware.py @@ -1,8 +1,12 @@ +import time +from datetime import datetime from collections.abc import Callable from typing import Any from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware +import logging +custom_logger = logging.getLogger("my_logger") class LoggerMiddleware(BaseHTTPMiddleware): async def dispatch( @@ -18,5 +22,22 @@ async def dispatch( @return Response from endpoint """ # TODO:(Member) Finish implementing this method + start_time = time.time() + timestamp = datetime.utcnow().isoformat() + + # Log incoming request + custom_logger.info(f"[{timestamp}] Incoming request: {request.method} {request.url}") + custom_logger.info(f"Headers: {dict(request.headers)}") + if request.query_params: + custom_logger.info(f"Query Params: {dict(request.query_params)}") + + # Process request response = await call_next(request) + + # Measure execution time + duration = time.time() - start_time + custom_logger.info( + f"Response status: {response.status_code} | Duration: {duration:.4f} seconds" + ) + return response diff --git a/backend/data/data_models.py b/backend/data/data_models.py index 68adddb..da787ad 100644 --- a/backend/data/data_models.py +++ b/backend/data/data_models.py @@ -33,7 +33,21 @@ def validate_params_format(self): The format of the comma seperated values is "data1,data2" so no spaces between data and the commas. """ # TODO: (Member) Implement this method - return self + if self.params is None and self.format is None: + return self # Valid case: both are None + + if self.params is not None and self.format is not None: + params_count = len(self.params.split(",")) + format_count = len(self.format.split(",")) + if params_count == format_count: + return self + else: + raise ValueError( + f"Mismatch between number of params ({params_count}) and format items ({format_count})." + ) + + + raise ValueError("Both 'params' and 'format' must be None or must have the same number of comma-separated values.") class Command(BaseSQLModel, table=True): From 62ced4d764186eadabf5e51cd44463fd9a8a5260 Mon Sep 17 00:00:00 2001 From: Prisha Patel <19prishpat@gmail.com> Date: Tue, 6 May 2025 23:11:13 -0400 Subject: [PATCH 2/2] Backend after feedback --- backend/api/endpoints/command.py | 6 ++--- backend/api/middlewares/logger_middleware.py | 12 +++++----- backend/data/data_models.py | 23 ++++++++++---------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/backend/api/endpoints/command.py b/backend/api/endpoints/command.py index bf97a7b..487ff08 100644 --- a/backend/api/endpoints/command.py +++ b/backend/api/endpoints/command.py @@ -31,13 +31,13 @@ def create_command(payload: CommandRequest, db: Session = Depends(get_db)): @param payload: The data used to create an item @return returns a json object with field of "data" under which there is the payload now pulled from the database """ - # TODO:(Member) Implement this endpoint - command = Command(**payload.model_dump()) + command = Command(**payload.dict()) db.add(command) db.commit() db.refresh(command) return {"data": command} - + + @command_router.delete("/{id}", response_model=CommandListResponse) diff --git a/backend/api/middlewares/logger_middleware.py b/backend/api/middlewares/logger_middleware.py index 460ce02..9bf25ac 100644 --- a/backend/api/middlewares/logger_middleware.py +++ b/backend/api/middlewares/logger_middleware.py @@ -1,12 +1,13 @@ -import time +from time import perf_counter from datetime import datetime from collections.abc import Callable from typing import Any from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware -import logging -custom_logger = logging.getLogger("my_logger") +from logging import getLogger +custom_logger = getLogger("my_logger") + class LoggerMiddleware(BaseHTTPMiddleware): async def dispatch( @@ -22,7 +23,8 @@ async def dispatch( @return Response from endpoint """ # TODO:(Member) Finish implementing this method - start_time = time.time() + start_time = perf_counter() + timestamp = datetime.utcnow().isoformat() # Log incoming request @@ -35,7 +37,7 @@ async def dispatch( response = await call_next(request) # Measure execution time - duration = time.time() - start_time + duration = perf_counter() - start_time custom_logger.info( f"Response status: {response.status_code} | Duration: {duration:.4f} seconds" ) diff --git a/backend/data/data_models.py b/backend/data/data_models.py index da787ad..14f5704 100644 --- a/backend/data/data_models.py +++ b/backend/data/data_models.py @@ -25,6 +25,7 @@ class MainCommand(BaseSQLModel, table=True): data_size: int total_size: int + @model_validator(mode="after") def validate_params_format(self): """ @@ -34,20 +35,18 @@ def validate_params_format(self): """ # TODO: (Member) Implement this method if self.params is None and self.format is None: - return self # Valid case: both are None + return self + if self.params is None or self.format is None: + raise ValueError("Both params and format should be None or both should be provided.") + + params_count = len(self.params.split(",")) + format_count = len(self.format.split(",")) - if self.params is not None and self.format is not None: - params_count = len(self.params.split(",")) - format_count = len(self.format.split(",")) - if params_count == format_count: - return self - else: - raise ValueError( - f"Mismatch between number of params ({params_count}) and format items ({format_count})." - ) + if params_count != format_count: + raise ValueError(f"Mismatch: params has {params_count} values, but format has {format_count}.") + + return self #if all checks pass return the instance - - raise ValueError("Both 'params' and 'format' must be None or must have the same number of comma-separated values.") class Command(BaseSQLModel, table=True):