Skip to content

Commit 3645e3f

Browse files
committed
Move handle_failure_and_cleanup_temp_tables to Db services to avoid in-function import
1 parent d50d2d2 commit 3645e3f

3 files changed

Lines changed: 67 additions & 70 deletions

File tree

app/airflow/dags/SR_processing_dag.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
from libs.utils import (
1111
connect_to_storage,
1212
create_task,
13-
handle_failure_and_cleanup_temp_tables,
1413
validate_params_SR_processing,
1514
)
15+
from libs.SR_processing.db_services import handle_failure_and_cleanup_temp_tables
1616

1717
"""
1818
This DAG automates the process of creating scan report tables, fields and values

app/airflow/dags/libs/SR_processing/db_services.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import time
23
from collections import defaultdict
34
from typing import Any, Dict, List, Tuple
45

@@ -9,6 +10,7 @@
910
AIRFLOW_DAGRUN_TIMEOUT,
1011
AIRFLOW_DEBUG_MODE,
1112
EXECUTE_VALUES_PAGE_SIZE,
13+
TEMP_TABLE_CLEANUP_DELAY,
1214
)
1315
from libs.utils import update_job_status
1416
from openpyxl.worksheet.worksheet import Worksheet
@@ -261,3 +263,67 @@ def cleanup_temp_tables_for_scan_report(scan_report_id: int) -> List[Tuple[str,
261263
if table_pairs:
262264
delete_temp_tables(scan_report_id, table_pairs)
263265
return table_pairs
266+
267+
def handle_failure_and_cleanup_temp_tables(context):
268+
"""
269+
Delete temporary tables when the DAG fails or times out.
270+
271+
This handles cleanup when failures happen outside the normal pipeline code, like
272+
timeouts or external errors. Since the tables are already in the database even if
273+
the DAG fails, we query mapping_scanreporttable to find all tables for this
274+
scan_report_id, then delete the temp tables (temp_data_dictionary and
275+
temp_field_values).
276+
277+
When a timeout occurs, the task that was running may still be creating temporary tables in the background.
278+
This function waits TEMP_TABLE_CLEANUP_DELAY seconds first so any in-flight table creation can finish,
279+
then runs a single cleanup pass. Cleanup is not urgent, so waiting once is simpler than cleaning twice.
280+
281+
282+
Args:
283+
context: Airflow execution context containing task_instance, dag, dag_run, etc.
284+
"""
285+
try:
286+
dag_run = context["dag_run"]
287+
dag = context.get("dag")
288+
dag_run_conf = dag_run.conf or {}
289+
scan_report_id = dag_run_conf.get("scan_report_id")
290+
291+
if not scan_report_id:
292+
logging.warning(
293+
"No scan_report_id found in DAG run configuration, skipping temp table cleanup"
294+
)
295+
return
296+
297+
# Update job status to FAILED for scan_report_processing DAG
298+
if dag and dag.dag_id == "scan_report_processing":
299+
try:
300+
update_job_status(
301+
stage=JobStageType.UPLOAD_SCAN_REPORT,
302+
status=StageStatusType.FAILED,
303+
scan_report=scan_report_id,
304+
details="Scan report processing DAG timed out or failed.",
305+
)
306+
logging.info(
307+
"Updated job status to FAILED for scan_report_id=%s",
308+
scan_report_id,
309+
)
310+
except Exception as e:
311+
logging.error("Failed to update job status on failure: %s", str(e))
312+
313+
# Wait so a timed-out task can finish creating tables, then delete the temporary tables
314+
delay = TEMP_TABLE_CLEANUP_DELAY
315+
time.sleep(delay)
316+
317+
table_pairs = cleanup_temp_tables_for_scan_report(scan_report_id)
318+
if table_pairs:
319+
logging.info(
320+
"Deleted temp tables for scan_report_id=%s (n=%d)",
321+
scan_report_id,
322+
len(table_pairs),
323+
)
324+
logging.info(
325+
"Completed temp table cleanup for scan_report_id=%s", scan_report_id
326+
)
327+
328+
except Exception as e:
329+
logging.error("Failed to delete temporary tables on failure: %s", str(e))

app/airflow/dags/libs/utils.py

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
AIRFLOW_VAR_MINIO_ENDPOINT,
1818
AIRFLOW_VAR_MINIO_SECRET_KEY,
1919
AIRFLOW_VAR_WASB_CONNECTION_STRING,
20-
TEMP_TABLE_CLEANUP_DELAY,
2120
storage_type,
2221
)
2322

@@ -217,74 +216,6 @@ def update_job_status_on_failure(context):
217216
logging.error(f"Failed to update job status on skipped task: {str(e)}")
218217

219218

220-
def handle_failure_and_cleanup_temp_tables(context):
221-
"""
222-
Delete temporary tables when the DAG fails or times out.
223-
224-
This handles cleanup when failures happen outside the normal pipeline code, like
225-
timeouts or external errors. Since the tables are already in the database even if
226-
the DAG fails, we query mapping_scanreporttable to find all tables for this
227-
scan_report_id, then delete the temp tables (temp_data_dictionary and
228-
temp_field_values).
229-
230-
When a timeout occurs, the task that was running may still be creating temporary tables in the background.
231-
This function waits TEMP_TABLE_CLEANUP_DELAY seconds first so any in-flight table creation can finish,
232-
then runs a single cleanup pass. Cleanup is not urgent, so waiting once is simpler than cleaning twice.
233-
234-
235-
Args:
236-
context: Airflow execution context containing task_instance, dag, dag_run, etc.
237-
"""
238-
try:
239-
dag_run = context["dag_run"]
240-
dag = context.get("dag")
241-
dag_run_conf = dag_run.conf or {}
242-
scan_report_id = dag_run_conf.get("scan_report_id")
243-
244-
if not scan_report_id:
245-
logging.warning(
246-
"No scan_report_id found in DAG run configuration, skipping temp table cleanup"
247-
)
248-
return
249-
250-
# Update job status to FAILED for scan_report_processing DAG
251-
if dag and dag.dag_id == "scan_report_processing":
252-
try:
253-
update_job_status(
254-
stage=JobStageType.UPLOAD_SCAN_REPORT,
255-
status=StageStatusType.FAILED,
256-
scan_report=scan_report_id,
257-
details="Scan report processing DAG timed out or failed.",
258-
)
259-
logging.info(
260-
"Updated job status to FAILED for scan_report_id=%s",
261-
scan_report_id,
262-
)
263-
except Exception as e:
264-
logging.error("Failed to update job status on failure: %s", str(e))
265-
266-
# Wait so a timed-out task can finish creating tables, then delete the temporary tables
267-
delay = TEMP_TABLE_CLEANUP_DELAY
268-
time.sleep(delay)
269-
270-
# I did this to avoid circular import
271-
from libs.SR_processing.db_services import cleanup_temp_tables_for_scan_report
272-
273-
table_pairs = cleanup_temp_tables_for_scan_report(scan_report_id)
274-
if table_pairs:
275-
logging.info(
276-
"Deleted temp tables for scan_report_id=%s (n=%d)",
277-
scan_report_id,
278-
len(table_pairs),
279-
)
280-
logging.info(
281-
"Completed temp table cleanup for scan_report_id=%s", scan_report_id
282-
)
283-
284-
except Exception as e:
285-
logging.error("Failed to delete temporary tables on failure: %s", str(e))
286-
287-
288219
def create_task(task_id, python_callable, dag, provide_context=True):
289220
"""Create a task in the DAG"""
290221
return PythonOperator(

0 commit comments

Comments
 (0)