Skip to content

Add facility to sync functions #126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions src/nsls2api/api/v1/jobs_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ async def sync_proposal_types(facility: FacilityName = FacilityName.nsls2):
include_in_schema=SYNC_ROUTES_IN_SCHEMA,
tags=["sync"],
)
async def sync_proposals_for_cycle(request: Request, cycle: str) -> BackgroundJob:
sync_params = JobSyncParameters(cycle=cycle)
async def sync_proposals_for_cycle(request: Request, cycle: str,
facility: FacilityName = FacilityName.nsls2) -> BackgroundJob:
sync_params = JobSyncParameters(cycle=cycle, facility=facility)
job = await background_service.create_background_job(
JobActions.synchronize_proposals_for_cycle,
sync_parameters=sync_params,
Expand All @@ -110,9 +111,9 @@ async def sync_cycles(facility: FacilityName = FacilityName.nsls2):
tags=["sync"],
)
async def sync_update_cycles(
request: fastapi.Request,
facility: FacilityName = FacilityName.nsls2,
cycle: Optional[str] = None,
request: fastapi.Request,
facility: FacilityName = FacilityName.nsls2,
cycle: Optional[str] = None,
):
sync_params = JobSyncParameters(facility=facility, sync_source=JobSyncSource.PASS)

Expand Down
4 changes: 2 additions & 2 deletions src/nsls2api/services/background_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ async def worker_function():
)
case JobActions.synchronize_proposals_for_cycle:
logger.info(
f"Processing job {job.id} to synchronize proposals for cycle {job.sync_parameters.cycle} (from {job.sync_parameters.sync_source})."
f"Processing job {job.id} to synchronize proposals for the {job.sync_parameters.facility} facilities cycle {job.sync_parameters.cycle} (from {job.sync_parameters.sync_source})."
)
await sync_service.worker_synchronize_proposals_for_cycle_from_pass(
job.sync_parameters.cycle
job.sync_parameters.cycle, job.sync_paramters.facility
)
case JobActions.synchronize_proposal_types:
logger.info(
Expand Down
13 changes: 6 additions & 7 deletions src/nsls2api/services/pass_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,11 @@ async def get_saf_from_proposal(
return saf_list


async def get_commissioning_proposals_by_year(
year: str, facility: FacilityName = FacilityName.nsls2
) -> Optional[list[PassProposal]]:
pass_facility = await facility_service.pass_id_for_facility(facility)
async def get_commissioning_proposals_by_year(year: str, facility_name: FacilityName = FacilityName.nsls2) -> Optional[list[PassProposal]]:

pass_facility = await facility_service.pass_id_for_facility(facility_name)
if not pass_facility:
error_message: str = f"Facility {facility} does not have a PASS ID."
error_message: str = f"Facility {facility_name} does not have a PASS ID."
logger.error(error_message)
raise PassException(error_message)

Expand All @@ -142,11 +141,11 @@ async def get_commissioning_proposals_by_year(
PassProposal(**commissioning_proposal)
)
except ValidationError as error:
error_message = f"Error validating commissioning proposal data received from PASS for year {str(year)} at {facility} facility."
error_message = f"Error validating commissioning proposal data received from PASS for year {str(year)} at {facility_name} facility."
logger.error(error_message)
raise PassException(error_message) from error
except Exception as error:
error_message = f"Error retrieving commissioning proposal information from PASS for year {str(year)} at {facility} facility."
error_message = f"Error retrieving commissioning proposal information from PASS for year {str(year)} at {facility_name} facility."
logger.exception(error_message)
raise PassException(error_message) from error

Expand Down
38 changes: 19 additions & 19 deletions src/nsls2api/services/proposal_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ async def recently_updated(count=5, beamline: str | None = None):
# return result


async def fetch_proposals_for_cycle(cycle_name: str) -> list[str]:
cycle = await Cycle.find_one(Cycle.name == cycle_name)
async def fetch_proposals_for_cycle(cycle_name: str, facility_name: FacilityName = FacilityName.nsls2) -> list[str]:
cycle = await Cycle.find_one(Cycle.name == cycle_name, Cycle.facility == facility_name)
if cycle is None:
raise LookupError(f"Cycle {cycle} not found in local database.")
return cycle.proposals
Expand Down Expand Up @@ -151,13 +151,13 @@ async def search_proposals(search_text: str) -> Optional[list[Proposal]]:

# Get a list of proposals that match the given criteria
async def fetch_proposals(
proposal_id: list[str] | None = None,
beamline: list[str] | None = None,
cycle: list[str] | None = None,
facility: list[str] | None = None,
page_size: int = 10,
page: int = 1,
include_directories: bool = False,
proposal_id: list[str] | None = None,
beamline: list[str] | None = None,
cycle: list[str] | None = None,
facility: list[str] | None = None,
page_size: int = 10,
page: int = 1,
include_directories: bool = False,
) -> Optional[list[ProposalFullDetails]]:
query = []

Expand Down Expand Up @@ -202,7 +202,7 @@ async def fetch_proposals(


async def proposal_type_description_from_pass_type_id(
pass_type_id: int,
pass_type_id: int,
) -> Optional[str]:
proposal_type = await ProposalType.find_one(
ProposalType.pass_id == str(pass_type_id)
Expand Down Expand Up @@ -245,7 +245,7 @@ async def fetch_users_on_proposal(proposal_id: str) -> Optional[list[User]]:


async def fetch_usernames_from_proposal(
proposal_id: str,
proposal_id: str,
) -> Optional[list[str]]:
proposal = await proposal_by_id(proposal_id)

Expand Down Expand Up @@ -304,18 +304,18 @@ async def has_valid_cycle(proposal: Proposal):
# If we don't have any cycles listed and this is not a commissioning
# proposal then the cycle information is invalid
return not (
(len(proposal.cycles) == 0)
and (
proposal.pass_type_id != 300005
or proposal.type == "Beamline Commissioning (beamline staff only)"
)
(len(proposal.cycles) == 0)
and (
proposal.pass_type_id != 300005
or proposal.type == "Beamline Commissioning (beamline staff only)"
)
)


async def is_commissioning(proposal: Proposal):
return (
proposal.pass_type_id == "300005"
or proposal.type == "Beamline Commissioning (beamline staff only)"
proposal.pass_type_id == "300005"
or proposal.type == "Beamline Commissioning (beamline staff only)"
)


Expand Down Expand Up @@ -439,7 +439,7 @@ async def generate_fake_proposal_id() -> int:


async def generate_fake_test_proposal(
facility_name: FacilityName = FacilityName.nsls2, add_specific_user=None
facility_name: FacilityName = FacilityName.nsls2, add_specific_user=None
) -> Optional[Proposal]:
"""
Generates a fake test proposal.
Expand Down
19 changes: 10 additions & 9 deletions src/nsls2api/services/sync_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,17 +317,17 @@ async def synchronize_proposal_from_pass(proposal_id: str) -> None:
logger.debug(f"Response: {response}")


async def update_proposals_with_cycle(cycle_name: str) -> None:
async def update_proposals_with_cycle(cycle_name: str, facility_name: FacilityName = FacilityName.nsls2) -> None:
"""
Update the cycle <-> proposals mapping for the given cycle.

:param cycle_name: The name of the cycle to process proposals for.
:type cycle_name: str
"""

proposal_list = await proposal_service.fetch_proposals_for_cycle(cycle_name)
proposal_list = await proposal_service.fetch_proposals_for_cycle(cycle_name, facility_name=facility_name)

logger.info(f"Found {len(proposal_list)} proposals for cycle {cycle_name}.")
logger.info(f"Found {len(proposal_list)} proposals for {facility_name} cycle {cycle_name}.")

for proposal_id in proposal_list:
# Add the cycle to the Proposal object
Expand All @@ -352,21 +352,22 @@ async def worker_synchronize_proposal_from_pass(proposal_id: str) -> None:
)


async def worker_synchronize_proposals_for_cycle_from_pass(cycle: str) -> None:
async def worker_synchronize_proposals_for_cycle_from_pass(cycle: str,
facility_name: FacilityName = FacilityName.nsls2) -> None:
start_time = datetime.datetime.now()

cycle_year = await facility_service.cycle_year(cycle)
cycle_year = await facility_service.cycle_year(cycle, facility_name=facility_name)

proposals = await proposal_service.fetch_proposals_for_cycle(cycle)
logger.info(f"Synchronizing {len(proposals)} proposals for {cycle} cycle.")
proposals = await proposal_service.fetch_proposals_for_cycle(cycle, facility_name=facility_name)
logger.info(f"Synchronizing {len(proposals)} proposals for facility {facility_name} in {cycle} cycle.")

for proposal_id in proposals:
logger.info(f"Synchronizing proposal {proposal_id}.")
await synchronize_proposal_from_pass(proposal_id)

commissioning_proposals: list[
PassProposal
] = await pass_service.get_commissioning_proposals_by_year(cycle_year)
] = await pass_service.get_commissioning_proposals_by_year(cycle_year, facility_name=facility_name)
logger.info(
f"Synchronizing {len(proposals)} commissioning proposals for the year {cycle_year}."
)
Expand All @@ -375,7 +376,7 @@ async def worker_synchronize_proposals_for_cycle_from_pass(cycle: str) -> None:
await synchronize_proposal_from_pass(str(proposal.Proposal_ID))

# Now update the cycle information for each proposal
await update_proposals_with_cycle(cycle)
await update_proposals_with_cycle(cycle, facility_name=facility_name)

time_taken = datetime.datetime.now() - start_time
logger.info(
Expand Down
Loading