From 66601cc39a4a2d5c29dbfb7d0e1535fb5edf9bc4 Mon Sep 17 00:00:00 2001 From: Stuart Campbell Date: Wed, 31 Jan 2024 16:54:51 -0500 Subject: [PATCH 1/5] Add FacilityCyclesResponseModel and update get_current_operating_cycle endpoint --- src/nsls2api/api/models/facility_model.py | 6 +++++- src/nsls2api/api/v1/facility_api.py | 20 ++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/nsls2api/api/models/facility_model.py b/src/nsls2api/api/models/facility_model.py index 95271508..44de4a0d 100644 --- a/src/nsls2api/api/models/facility_model.py +++ b/src/nsls2api/api/models/facility_model.py @@ -1,7 +1,11 @@ from enum import Enum - +import pydantic class FacilityName(Enum): nsls2 = "nsls2" lbms = "lbms" cfn = "cfn" + +class FacilityCyclesResponseModel(pydantic.BaseModel): + facility: str + cycles: list[str] \ No newline at end of file diff --git a/src/nsls2api/api/v1/facility_api.py b/src/nsls2api/api/v1/facility_api.py index d1c94b63..0fe1a3ec 100644 --- a/src/nsls2api/api/v1/facility_api.py +++ b/src/nsls2api/api/v1/facility_api.py @@ -1,6 +1,6 @@ import fastapi -from nsls2api.api.models.facility_model import FacilityName +from nsls2api.api.models.facility_model import FacilityName, FacilityCyclesResponseModel from nsls2api.services import proposal_service, facility_service router = fastapi.APIRouter() @@ -8,10 +8,22 @@ # TODO: Add back into schema when implemented. @router.get( - "/facility/{facility}/cycles/current", response_model=str, include_in_schema=False + "/facility/{facility}/cycles/current", response_model=FacilityCyclesResponseModel, include_in_schema=True ) -async def get_current_facilty_cycle(facility: FacilityName): - return "2024-1" +async def get_current_operating_cycle(facility: FacilityName): + current_cycle = await facility_service.current_operating_cycle(facility.name) + if current_cycle is None: + return fastapi.responses.JSONResponse( + {"error": f"No current operating cycle was found for facility {facility.name}"}, + status_code=404, + ) + + print("Are we healthy ? ") + print(await facility_service.is_healthy(facility.name)) + + response_model = FacilityCyclesResponseModel(facility=facility.name, cycles=[current_cycle]) + + return response_model @router.get("/facility/{facility}/cycles", include_in_schema=True) async def get_facility_cycles(facility: FacilityName): From c1059e631423c70d2f4d485617174ec67f1f48b2 Mon Sep 17 00:00:00 2001 From: Stuart Campbell Date: Thu, 1 Feb 2024 10:12:45 -0500 Subject: [PATCH 2/5] Add current_operating_cycle field to Cycle model and current_operating_cycle method to Facility service --- src/nsls2api/models/cycles.py | 1 + src/nsls2api/services/facility_service.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/nsls2api/models/cycles.py b/src/nsls2api/models/cycles.py index 1cb1d7de..61747853 100644 --- a/src/nsls2api/models/cycles.py +++ b/src/nsls2api/models/cycles.py @@ -8,6 +8,7 @@ class Cycle(beanie.Document): name: str accepting_proposals: Optional[bool] + current_operating_cycle: bool = False active: bool = False end_date: Optional[datetime.datetime] facility: str diff --git a/src/nsls2api/services/facility_service.py b/src/nsls2api/services/facility_service.py index f9e50aa7..53114e82 100644 --- a/src/nsls2api/services/facility_service.py +++ b/src/nsls2api/services/facility_service.py @@ -33,3 +33,23 @@ async def data_roles_by_user(username: str) -> Optional[list[str]]: facilities = await Facility.find(In(Facility.data_admins, [username])).to_list() facility_names = [f.facility_id for f in facilities if f.facility_id is not None] return facility_names + + +async def current_operating_cycle(facility: str) -> Optional[str]: + """ + Current Operating Cycle + + This method retrieves the current operating cycle for a given facility. + + :param facility: The facility name (str). + :return: The current operating cycle (str) or None if no current operating cycle is found. + """ + cycle = await Cycle.find_one( + Cycle.facility == facility, + Cycle.current_operating_cycle == True, # noqa: E712 + ) + + if cycle is None: + return None + + return cycle.name From f57a8acca58bb6eeb0cf0084ad2684e70d63ee1f Mon Sep 17 00:00:00 2001 From: Stuart Campbell Date: Thu, 1 Feb 2024 12:15:03 -0500 Subject: [PATCH 3/5] Update current_operating_cycle field name to is_current_operating_cycle --- src/nsls2api/models/cycles.py | 2 +- src/nsls2api/services/facility_service.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nsls2api/models/cycles.py b/src/nsls2api/models/cycles.py index 61747853..b99c0e20 100644 --- a/src/nsls2api/models/cycles.py +++ b/src/nsls2api/models/cycles.py @@ -8,7 +8,7 @@ class Cycle(beanie.Document): name: str accepting_proposals: Optional[bool] - current_operating_cycle: bool = False + is_current_operating_cycle: bool = False active: bool = False end_date: Optional[datetime.datetime] facility: str diff --git a/src/nsls2api/services/facility_service.py b/src/nsls2api/services/facility_service.py index 53114e82..997c35e2 100644 --- a/src/nsls2api/services/facility_service.py +++ b/src/nsls2api/services/facility_service.py @@ -46,7 +46,7 @@ async def current_operating_cycle(facility: str) -> Optional[str]: """ cycle = await Cycle.find_one( Cycle.facility == facility, - Cycle.current_operating_cycle == True, # noqa: E712 + Cycle.is_current_operating_cycle == True, # noqa: E712 ) if cycle is None: From ac036ce5a0a2f8058bb571c42b7f6a491f7b58aa Mon Sep 17 00:00:00 2001 From: Stuart Campbell Date: Thu, 1 Feb 2024 14:36:33 -0500 Subject: [PATCH 4/5] Comment out health check for now --- src/nsls2api/api/v1/facility_api.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nsls2api/api/v1/facility_api.py b/src/nsls2api/api/v1/facility_api.py index 0fe1a3ec..69af667e 100644 --- a/src/nsls2api/api/v1/facility_api.py +++ b/src/nsls2api/api/v1/facility_api.py @@ -18,8 +18,9 @@ async def get_current_operating_cycle(facility: FacilityName): status_code=404, ) - print("Are we healthy ? ") - print(await facility_service.is_healthy(facility.name)) + # TODO: Maybe add a health check here + # print("Are we healthy ? ") + # print(await facility_service.is_healthy(facility.name)) response_model = FacilityCyclesResponseModel(facility=facility.name, cycles=[current_cycle]) From 1490e774dfdedf8b60bd7a263e98136adbe0d207 Mon Sep 17 00:00:00 2001 From: Stuart Campbell Date: Thu, 1 Feb 2024 14:44:05 -0500 Subject: [PATCH 5/5] Add new API endpoint for retrieving current operating cycle --- src/nsls2api/api/models/facility_model.py | 6 +++- src/nsls2api/api/v1/facility_api.py | 36 +++++++++++++++++------ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/nsls2api/api/models/facility_model.py b/src/nsls2api/api/models/facility_model.py index 44de4a0d..5e6b2fb2 100644 --- a/src/nsls2api/api/models/facility_model.py +++ b/src/nsls2api/api/models/facility_model.py @@ -8,4 +8,8 @@ class FacilityName(Enum): class FacilityCyclesResponseModel(pydantic.BaseModel): facility: str - cycles: list[str] \ No newline at end of file + cycles: list[str] + +class FacilityCurrentOperatingCycleResponseModel(pydantic.BaseModel): + facility: str + cycle: str \ No newline at end of file diff --git a/src/nsls2api/api/v1/facility_api.py b/src/nsls2api/api/v1/facility_api.py index 69af667e..59493888 100644 --- a/src/nsls2api/api/v1/facility_api.py +++ b/src/nsls2api/api/v1/facility_api.py @@ -1,6 +1,10 @@ import fastapi -from nsls2api.api.models.facility_model import FacilityName, FacilityCyclesResponseModel +from nsls2api.api.models.facility_model import ( + FacilityName, + FacilityCyclesResponseModel, + FacilityCurrentOperatingCycleResponseModel, +) from nsls2api.services import proposal_service, facility_service router = fastapi.APIRouter() @@ -8,25 +12,36 @@ # TODO: Add back into schema when implemented. @router.get( - "/facility/{facility}/cycles/current", response_model=FacilityCyclesResponseModel, include_in_schema=True + "/facility/{facility}/cycles/current", + response_model=FacilityCurrentOperatingCycleResponseModel, + include_in_schema=True, ) async def get_current_operating_cycle(facility: FacilityName): current_cycle = await facility_service.current_operating_cycle(facility.name) if current_cycle is None: return fastapi.responses.JSONResponse( - {"error": f"No current operating cycle was found for facility {facility.name}"}, + { + "error": f"No current operating cycle was found for facility {facility.name}" + }, status_code=404, ) - + # TODO: Maybe add a health check here # print("Are we healthy ? ") # print(await facility_service.is_healthy(facility.name)) - response_model = FacilityCyclesResponseModel(facility=facility.name, cycles=[current_cycle]) - + response_model = FacilityCurrentOperatingCycleResponseModel( + facility=facility.name, cycle=current_cycle + ) + return response_model -@router.get("/facility/{facility}/cycles", include_in_schema=True) + +@router.get( + "/facility/{facility}/cycles", + response_model=FacilityCyclesResponseModel, + include_in_schema=True, +) async def get_facility_cycles(facility: FacilityName): cycle_list = await facility_service.facility_cycles(facility.name) if cycle_list is None: @@ -34,8 +49,11 @@ async def get_facility_cycles(facility: FacilityName): {"error": f"No cycles were found for facility {facility.name}"}, status_code=404, ) - data = {"facility": facility.name, "cycles": cycle_list} - return data + response_model = FacilityCyclesResponseModel( + facility=facility.name, cycles=cycle_list + ) + return response_model + @router.get("/facility/{facility}/cycle/{cycle}/proposals", include_in_schema=True) async def get_proposals_for_cycle(facility: FacilityName, cycle: str):