Skip to content

Commit 61c0523

Browse files
authored
fix: failures not being properly audited in foundry pipeline #94
2 parents 6d342c5 + 5ca0608 commit 61c0523

5 files changed

Lines changed: 58 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## v0.7.4 (2026-04-17)
2+
3+
### Fix
4+
5+
- fix failures not being properly audited in foundry pipeline
6+
17
## v0.7.3 (2026-04-16)
28

39
### Fix

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Issues = "https://github.com/NHSDigital/data-validation-engine/issues"
2424
Changelog = "https://github.com/NHSDigital/data-validation-engine/blob/main/CHANGELOG.md"
2525

2626
[tool.poetry]
27-
version = "0.7.3"
27+
version = "0.7.4"
2828
packages = [
2929
{ include = "dve", from = "src" },
3030
]

src/dve/pipeline/foundry_ddb_pipeline.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ def run_pipeline(
152152
)
153153
if sub_stats:
154154
self._audit_tables.add_submission_statistics_records(sub_stats=[sub_stats])
155+
else:
156+
self._audit_tables.mark_failed(submissions=[sub_id])
157+
155158
except Exception as err: # pylint: disable=W0718
156159
self._logger.exception(
157160
f"During processing of submission_id: {sub_id}, this exception was raised:"

src/dve/pipeline/pipeline.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ def data_contract_step(
527527

528528
return processed_files, failed_processing
529529

530-
def apply_business_rules(
530+
def apply_business_rules( # pylint: disable=R0914
531531
self, submission_info: SubmissionInfo, submission_status: Optional[SubmissionStatus] = None
532532
) -> tuple[SubmissionInfo, SubmissionStatus]:
533533
"""Apply the business rules to a given submission, the submission may have failed at the
@@ -581,15 +581,23 @@ def apply_business_rules(
581581

582582
key_fields = {model: conf.reporting_fields for model, conf in model_config.items()}
583583

584-
self.step_implementations.apply_rules(working_directory, entity_manager, rules, key_fields) # type: ignore
584+
_errors_uri, rules_success = self.step_implementations.apply_rules( # type: ignore
585+
working_directory,
586+
entity_manager,
587+
rules,
588+
key_fields
589+
)
585590

586591
rule_messages = load_feedback_messages(
587592
get_feedback_errors_uri(working_directory, "business_rules")
588593
)
589-
submission_status.validation_failed = (
594+
if (
590595
any(not rule_message.is_informational for rule_message in rule_messages)
591596
or submission_status.validation_failed
592-
)
597+
):
598+
submission_status.validation_failed = True
599+
elif not rules_success:
600+
submission_status.processing_failed = True
593601

594602
for entity_name, entity in entity_manager.entities.items():
595603
projected = self._step_implementations.write_parquet( # type: ignore

tests/test_pipeline/test_foundry_ddb_pipeline.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,39 @@ def test_foundry_runner_with_submitted_files_path(movies_test_files, temp_ddb_co
192192
assert fh.get_resource_exists(report_uri)
193193
assert len(list(fh.iter_prefix(output_loc))) == 2
194194
assert len(list(fh.iter_prefix(audit_files))) == 3
195+
196+
197+
def test_foundry_runner_error_at_bi_rules(movies_test_files, temp_ddb_conn):
198+
# Missing refdata in the business rules should cause a handled failure
199+
db_file, conn = temp_ddb_conn
200+
processing_folder = Path(tempfile.mkdtemp()).as_posix()
201+
submitted_files_path = Path(movies_test_files).as_posix()
202+
sub_id = uuid4().hex
203+
sub_info = SubmissionInfo(
204+
submission_id=sub_id,
205+
dataset_id="movies",
206+
file_name="good_movies",
207+
file_extension="json",
208+
submitting_org="TEST",
209+
datetime_received=datetime(2025,11,5)
210+
)
211+
212+
DuckDBRefDataLoader.connection = conn
213+
DuckDBRefDataLoader.dataset_config_uri = None
214+
215+
with DDBAuditingManager(db_file.as_uri(), None, conn) as audit_manager:
216+
dve_pipeline = FoundryDDBPipeline(
217+
processed_files_path=processing_folder,
218+
audit_tables=audit_manager,
219+
connection=conn,
220+
rules_path=get_test_file_path("movies/movies_ddb.dischema.json").as_posix(),
221+
submitted_files_path=submitted_files_path,
222+
reference_data_loader=DuckDBRefDataLoader,
223+
)
224+
output_loc, report_uri, audit_files = dve_pipeline.run_pipeline(sub_info)
225+
226+
assert Path(processing_folder, sub_id, sub_info.file_name_with_ext).exists()
227+
assert output_loc is None
228+
assert len(list(fh.iter_prefix(audit_files))) == 2
229+
assert audit_manager.get_submission_status(sub_id).processing_failed
230+
assert audit_manager.get_latest_processing_records().select("submission_result").pl().to_dicts()[0]["submission_result"] == "processing_failed"

0 commit comments

Comments
 (0)