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
7 changes: 6 additions & 1 deletion src/services/mwl/create_worklist_item.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging

from services.storage import MWLStorage, WorklistItem
from services.storage import DuplicateWorklistItemError, MWLStorage, WorklistItem

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -38,6 +38,11 @@ def call(self, payload: dict):
)
logger.info(f"Created worklist item: {item.get('accession_number')}")
return {"status": "created", "action_id": action_id}
except DuplicateWorklistItemError:
logger.warning(
f"Duplicate worklist item ignored: accession_number={item.get('accession_number')!r}, action_id={action_id!r}"
)
return {"status": "duplicate", "action_id": action_id}
except Exception as e:
logger.error(f"Failed to create worklist item: {e}")
return {"status": "error", "action_id": action_id, "error": str(e)}
37 changes: 23 additions & 14 deletions src/services/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,12 @@ class WorklistItemNotFoundError(Exception):
pass


class DuplicateWorklistItemError(Exception):
"""Raised when a worklist item with the same accession number already exists."""

pass


class MWLStorage(Storage):
def __init__(self, db_path: str = "/var/lib/pacs/worklist.db"):
"""
Expand Down Expand Up @@ -336,20 +342,23 @@ def store_worklist_item(
Raises:
sqlite3.IntegrityError: If accession number already exists
"""
with self._get_connection() as conn:
conn.execute(
(
"INSERT INTO worklist_items (accession_number, modality, patient_birth_date, "
"patient_id, patient_name, patient_sex, procedure_code, scheduled_date, "
"scheduled_time, source_message_id, study_description, study_instance_uid) "
"VALUES (:accession_number, :modality, :patient_birth_date, "
":patient_id, :patient_name, :patient_sex, :procedure_code, "
":scheduled_date, :scheduled_time, :source_message_id, "
":study_description, :study_instance_uid)"
),
worklist_item.__dict__,
)
conn.commit()
try:
with self._get_connection() as conn:
conn.execute(
(
"INSERT INTO worklist_items (accession_number, modality, patient_birth_date, "
"patient_id, patient_name, patient_sex, procedure_code, scheduled_date, "
"scheduled_time, source_message_id, study_description, study_instance_uid) "
"VALUES (:accession_number, :modality, :patient_birth_date, "
":patient_id, :patient_name, :patient_sex, :procedure_code, "
":scheduled_date, :scheduled_time, :source_message_id, "
":study_description, :study_instance_uid)"
),
worklist_item.__dict__,
)
conn.commit()
except sqlite3.IntegrityError:
raise DuplicateWorklistItemError(f"Worklist item already exists: {worklist_item.accession_number}")

return worklist_item.accession_number

Expand Down
14 changes: 13 additions & 1 deletion tests/services/mwl/test_create_worklist_item.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from unittest.mock import patch

from services.mwl.create_worklist_item import CreateWorklistItem
from services.storage import WorklistItem
from services.storage import DuplicateWorklistItemError, WorklistItem


@patch(f"{CreateWorklistItem.__module__}.MWLStorage")
Expand Down Expand Up @@ -40,6 +40,18 @@ def test_call_missing_action_id(self, mock_mwl_storage, listener_payload):

mock_storage_instance.store_worklist_item.assert_not_called()

def test_call_duplicate_worklist_item(self, mock_mwl_storage, listener_payload):
mock_storage_instance = mock_mwl_storage.return_value
mock_storage_instance.store_worklist_item.side_effect = DuplicateWorklistItemError(
"Worklist item already exists: ACC999999"
)
subject = CreateWorklistItem(mock_storage_instance)

response = subject.call(listener_payload)
assert response == {"status": "duplicate", "action_id": "action-12345"}

mock_storage_instance.store_worklist_item.assert_called_once()

def test_call_storage_exception(self, mock_mwl_storage, listener_payload):
mock_storage_instance = mock_mwl_storage.return_value
mock_storage_instance.store_worklist_item.side_effect = Exception("DB error")
Expand Down
Loading