Skip to content
Open
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 backend/workflow_manager/endpoint_v2/database_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,13 @@ def get_columns_and_values(
if error and has_error_col:
values[TableColumns.ERROR_MESSAGE] = error
if has_status_col:
# Use `.value` so the destination column stores the plain string
# ("SUCCESS"/"ERROR"), not the enum repr ("FileProcessingStatus.SUCCESS")
# that stringifying the member produces.
values[TableColumns.STATUS] = (
FileProcessingStatus.ERROR if error else FileProcessingStatus.SUCCESS
FileProcessingStatus.ERROR.value
if error
else FileProcessingStatus.SUCCESS.value
)
if column_mode == ColumnModes.WRITE_JSON_TO_A_SINGLE_COLUMN:
v2_col_name = f"{single_column_name}_v2"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Regression test for UN-3735.

The destination `status` column must be written as the plain string
"SUCCESS"/"ERROR", never the enum repr "FileProcessingStatus.SUCCESS".

The backend ``FileProcessingStatus`` is a plain ``Enum``, so a stringified member
renders as "FileProcessingStatus.SUCCESS"; the assertions check ``str(value)`` —
what the DB driver persists. No DB access needed, so ``SimpleTestCase``.
"""

from django.test import SimpleTestCase

from workflow_manager.endpoint_v2.constants import TableColumns
from workflow_manager.endpoint_v2.database_utils import DatabaseUtils


class DestinationStatusValueTests(SimpleTestCase):
def _status_for(self, error: str | None) -> object:
values = DatabaseUtils.get_columns_and_values(
column_mode_str="WRITE_JSON_TO_A_SINGLE_COLUMN",
data={"k": "v"},
file_path="f",
execution_id="e",
table_info={
"status": "STRING",
"error_message": "STRING",
"data": "STRING",
},
error=error,
)
return values[TableColumns.STATUS]

def test_status_success_is_plain_string(self) -> None:
self.assertEqual(str(self._status_for(None)), "SUCCESS")

def test_status_error_is_plain_string(self) -> None:
self.assertEqual(str(self._status_for("boom")), "ERROR")
8 changes: 6 additions & 2 deletions workers/shared/infrastructure/database/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,10 +308,14 @@ def _add_processing_columns(
if error and has_error_col:
values[TableColumns.ERROR_MESSAGE] = error

# Add status based on error presence
# Add status based on error presence. Use `.value` so the destination
# column stores the plain string ("SUCCESS"/"ERROR"), not the enum repr
# ("FileProcessingStatus.SUCCESS") that stringifying the member produces.
if has_status_col:
values[TableColumns.STATUS] = (
FileProcessingStatus.ERROR if error else FileProcessingStatus.SUCCESS
FileProcessingStatus.ERROR.value
if error
else FileProcessingStatus.SUCCESS.value
)

@staticmethod
Expand Down
35 changes: 35 additions & 0 deletions workers/tests/test_destination_status_value.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Regression test for UN-3735.

The destination `status` column must be written as the plain string
"SUCCESS"/"ERROR", never the enum repr "FileProcessingStatus.SUCCESS".

Subtlety: ``FileProcessingStatus`` is a ``(str, Enum)``, so the *member* already
compares equal to its value ("SUCCESS"). The bug only shows when the value is
**stringified** on the way into the DB insert (``str(member)`` →
"FileProcessingStatus.SUCCESS"). So these tests assert on ``str(value)`` — what
the DB driver actually persists — not on ``==``.
"""

from shared.enums.status_enums import FileProcessingStatus
from shared.infrastructure.database.utils import TableColumns, WorkerDatabaseUtils


def test_processing_status_success_is_plain_string() -> None:
values: dict = {}
WorkerDatabaseUtils._add_processing_columns(
values, table_info=None, metadata=None, error=None
)
assert str(values[TableColumns.STATUS]) == "SUCCESS"
assert values[TableColumns.STATUS] == FileProcessingStatus.SUCCESS.value
# It must be a plain str, not the enum member (which stringifies to the repr).
assert not isinstance(values[TableColumns.STATUS], FileProcessingStatus)


def test_processing_status_error_is_plain_string() -> None:
values: dict = {}
WorkerDatabaseUtils._add_processing_columns(
values, table_info={"status": "STRING"}, metadata=None, error="boom"
)
assert str(values[TableColumns.STATUS]) == "ERROR"
assert values[TableColumns.STATUS] == FileProcessingStatus.ERROR.value
assert not isinstance(values[TableColumns.STATUS], FileProcessingStatus)
Loading