Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 15 additions & 0 deletions app/database/models/processing_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,21 @@ def get_job_by_user_id(
)


def remove_job_by_id(database: Session, job_id: int, user_id: str) -> bool:
logger.info(f"Removing processing job with ID {job_id} for user {user_id}")
job = get_job_by_user_id(database, job_id, user_id)
if job:
database.delete(job)
database.commit()
return True
else:
logger.warning(
f"Could not remove processing job with ID {job_id} for user {user_id} as it could not"
" be found in the database"
)
return False


def update_job_status_by_id(
database: Session, job_id: int, status: ProcessingStatusEnum
):
Expand Down
46 changes: 46 additions & 0 deletions app/routers/unit_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
)
from app.services.processing import (
create_processing_job,
delete_processing_job,
get_processing_job_by_user_id,
get_processing_job_results,
)
Expand Down Expand Up @@ -222,3 +223,48 @@ async def get_job_results(
raise InternalException(
message="An error occurred while retrieving processing job results."
)


@router.delete(
"/unit_jobs/{job_id}",
tags=["Unit Jobs"],
responses={
JobNotFoundException.http_status: {
"description": "Job not found",
"model": ErrorResponse,
"content": {
"application/json": {
"example": get_dispatcher_error_response(
JobNotFoundException(), "request-id"
)
}
},
},
InternalException.http_status: {
"description": "Internal server error",
"model": ErrorResponse,
"content": {
"application/json": {
"example": get_dispatcher_error_response(
InternalException(), "request-id"
)
}
},
},
},
)
async def delete_job(
job_id: int, db: Session = Depends(get_db), token: str = Depends(oauth2_scheme)
) -> None:
try:
job = await get_processing_job_by_user_id(token, db, job_id)
if not job:
raise JobNotFoundException()
await delete_processing_job(token, db, job_id)
except DispatcherException as de:
raise de
except Exception as e:
logger.error(f"Error deleting processing job {job_id}: {e}")
raise InternalException(
message="An error occurred while deleting the processing job."
)
20 changes: 20 additions & 0 deletions app/services/processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ProcessingJobRecord,
get_job_by_user_id,
get_jobs_by_user_id,
remove_job_by_id,
save_job_to_db,
update_job_status_by_id,
)
Expand Down Expand Up @@ -228,3 +229,22 @@ async def retrieve_service_parameters(
user_token=user_token,
details=payload.service,
)


async def delete_processing_job(
token: str,
database: Session,
job_id: int,
) -> None:
user = get_current_user_id(token)
logger.info(f"Deleting processing job with ID {job_id} for user {user}")

record = get_job_by_user_id(database, job_id, user)
if not record:
return

# @TODO - Cancel job on the platform as well when supported by the platform
# platform = get_processing_platform(record.label)
# await platform.cancel_job(user_token=token, job_id=record.platform_job_id)

remove_job_by_id(database, record.id, user)
38 changes: 38 additions & 0 deletions tests/routers/test_unit_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,41 @@ def test_unit_jobs_get_job_results_500(mock_get_processing_job_results, client):
assert "An error occurred while retrieving processing job results." in r.json().get(
"message", ""
)


@patch("app.routers.unit_jobs.delete_processing_job")
@patch("app.routers.unit_jobs.get_processing_job_by_user_id")
def test_unit_jobs_delete_job_200(
mock_get_processing_job,
mock_delete_processing_job,
client,
fake_processing_job,
):

mock_get_processing_job.return_value = fake_processing_job
mock_delete_processing_job.return_value = None

r = client.delete("/unit_jobs/1")
assert r.status_code == 200


@patch("app.routers.unit_jobs.get_processing_job_by_user_id")
def test_unit_jobs_delete_job_results_404(mock_get_processing_job, client):

mock_get_processing_job.return_value = None

r = client.delete("/unit_jobs/1")
assert r.status_code == status.HTTP_404_NOT_FOUND
assert "The requested job was not found." in r.json().get("message", "")


@patch("app.routers.unit_jobs.get_processing_job_by_user_id")
def test_unit_jobs_delete_job_500(mock_get_processing_job, client):

mock_get_processing_job.side_effect = RuntimeError("Database connection lost")

r = client.delete("/unit_jobs/1")
assert r.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert "An error occurred while deleting the processing job." in r.json().get(
"message", ""
)
42 changes: 42 additions & 0 deletions tests/services/test_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from app.services.processing import (
create_processing_job,
create_synchronous_job,
delete_processing_job,
get_processing_job_results,
get_job_status,
get_processing_job_by_user_id,
Expand Down Expand Up @@ -555,3 +556,44 @@ async def test_retrieve_service_parameters_success(
details=fake_param_request.service,
)
assert result == fake_parameter_result


@pytest.mark.asyncio
@patch("app.services.processing.remove_job_by_id")
@patch("app.services.processing.get_job_by_user_id")
@patch("app.services.processing.get_current_user_id")
async def test_delete_processing_job_deletes_record_when_found(
mock_current_user,
mock_get_job,
mock_remove_job,
fake_db_session,
fake_processing_job_record,
):
mock_current_user.return_value = "foobar"
mock_get_job.return_value = fake_processing_job_record

await delete_processing_job("foobar-token", fake_db_session, 1)

mock_get_job.assert_called_once_with(fake_db_session, 1, "foobar")
mock_remove_job.assert_called_once_with(
fake_db_session, fake_processing_job_record.id, "foobar"
)


@pytest.mark.asyncio
@patch("app.services.processing.remove_job_by_id")
@patch("app.services.processing.get_job_by_user_id")
@patch("app.services.processing.get_current_user_id")
async def test_delete_processing_job_noop_when_not_found(
mock_current_user,
mock_get_job,
mock_remove_job,
fake_db_session,
):
mock_current_user.return_value = "foobar"
mock_get_job.return_value = None

await delete_processing_job("foobar-token", fake_db_session, 1)

mock_get_job.assert_called_once_with(fake_db_session, 1, "foobar")
mock_remove_job.assert_not_called()
Loading