Skip to content

Commit 49832f0

Browse files
Handle corrupt backfill rows in tag counts
1 parent 9711f02 commit 49832f0

2 files changed

Lines changed: 70 additions & 5 deletions

File tree

python_modules/dagster/dagster/_core/storage/runs/sql_run_storage.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import sqlalchemy as db
1212
import sqlalchemy.exc as db_exc
13-
from dagster_shared.serdes import deserialize_values
1413
from dagster_shared.seven import JSONDecodeError
1514
from sqlalchemy.engine import Connection
1615

@@ -1094,9 +1093,7 @@ def get_backfills_count(self, filters: BulkActionsFilter | None = None) -> int:
10941093
# also have the requested tags. This requires fetching the backfills from the db and filtering them
10951094
query = self._backfills_query(filters=filters)
10961095
rows = self.fetchall(query)
1097-
backfill_candidates = deserialize_values(
1098-
(row["body"] for row in rows), PartitionBackfill
1099-
)
1096+
backfill_candidates = self._deserialize_backfill_rows(rows)
11001097
return len(
11011098
self._apply_backfill_tags_filter_to_results(backfill_candidates, filters.tags)
11021099
)

python_modules/dagster/dagster_tests/storage_tests/utils/run_storage.py

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from dagster._core.storage.root import LocalArtifactStorage
2525
from dagster._core.storage.runs.base import RunStorage
2626
from dagster._core.storage.runs.migration import REQUIRED_DATA_MIGRATIONS
27-
from dagster._core.storage.runs.schema import BulkActionsTable
27+
from dagster._core.storage.runs.schema import BackfillTagsTable, BulkActionsTable
2828
from dagster._core.storage.runs.sql_run_storage import SqlRunStorage
2929
from dagster._core.storage.tags import (
3030
BACKFILL_ID_TAG,
@@ -1450,6 +1450,14 @@ def test_get_backfills_skips_corrupt_backfill_rows(
14501450
backfill_timestamp=time.time(),
14511451
)
14521452
storage.add_backfill(valid_backfill)
1453+
storage.add_run(
1454+
create_dagster_run(
1455+
run_id=make_new_run_id(),
1456+
job_name="some_pipeline",
1457+
status=DagsterRunStatus.SUCCESS,
1458+
tags={"foo": "bar", BACKFILL_ID_TAG: valid_backfill.backfill_id},
1459+
)
1460+
)
14531461

14541462
with storage.connect() as conn:
14551463
conn.execute(
@@ -1510,6 +1518,66 @@ def test_get_backfills_limit_skips_corrupt_rows_without_shrinking_page(
15101518

15111519
assert "Skipping backfill corrupt because it could not be deserialized." in caplog.text
15121520

1521+
def test_get_backfills_count_with_tags_skips_corrupt_rows(
1522+
self, storage: RunStorage, caplog: pytest.LogCaptureFixture
1523+
):
1524+
if not isinstance(storage, SqlRunStorage):
1525+
pytest.skip("storage is not SQL-backed")
1526+
if not self.supports_backfill_tags_filtering_queries():
1527+
pytest.skip("storage does not support filtering backfills by tag")
1528+
if not self.supports_backfills_count():
1529+
pytest.skip("storage does not support backfill count")
1530+
1531+
origin = self.fake_partition_set_origin("fake_partition_set")
1532+
valid_backfill = PartitionBackfill(
1533+
"valid",
1534+
partition_set_origin=origin,
1535+
status=BulkActionStatus.REQUESTED,
1536+
partition_names=["a", "b", "c"],
1537+
from_failure=False,
1538+
tags={"foo": "bar"},
1539+
backfill_timestamp=time.time(),
1540+
)
1541+
storage.add_backfill(valid_backfill)
1542+
storage.add_run(
1543+
create_dagster_run(
1544+
run_id=make_new_run_id(),
1545+
job_name="some_pipeline",
1546+
status=DagsterRunStatus.SUCCESS,
1547+
tags={"foo": "bar", BACKFILL_ID_TAG: valid_backfill.backfill_id},
1548+
)
1549+
)
1550+
1551+
with storage.connect() as conn:
1552+
conn.execute(
1553+
BulkActionsTable.insert().values(
1554+
key="corrupt",
1555+
status=BulkActionStatus.REQUESTED.value,
1556+
timestamp=datetime_from_timestamp(time.time()),
1557+
body='{"truncated"',
1558+
)
1559+
)
1560+
conn.execute(
1561+
BackfillTagsTable.insert().values(
1562+
backfill_id="corrupt",
1563+
key="foo",
1564+
value="bar",
1565+
)
1566+
)
1567+
storage.add_run(
1568+
create_dagster_run(
1569+
run_id=make_new_run_id(),
1570+
job_name="some_pipeline",
1571+
status=DagsterRunStatus.SUCCESS,
1572+
tags={"foo": "bar", BACKFILL_ID_TAG: "corrupt"},
1573+
)
1574+
)
1575+
1576+
with caplog.at_level("WARNING", logger="dagster"):
1577+
assert storage.get_backfills_count(BulkActionsFilter(tags={"foo": "bar"})) == 1
1578+
1579+
assert "Skipping backfill corrupt because it could not be deserialized." in caplog.text
1580+
15131581
def test_backfill_status_filtering(self, storage: RunStorage):
15141582
origin = self.fake_partition_set_origin("fake_partition_set")
15151583
backfills = storage.get_backfills()

0 commit comments

Comments
 (0)