Repository navigation
Fixes #34479: skip stale-pipeline deletion when Data 360 listing is incomplete - #34537
Conversation
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
✅ Playwright Results — workflow succeededValidated commit ✅ 105 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky PerformanceBlocking targets: ✅ met · Optimization targets: 🟡 in progress Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting. 🕒 Full workflow signal wall (to summary) 1h 44m 2s ⏱️ Max setup 4m 48s · max shard execution 15m 10s · max shard-job elapsed before upload 21m 25s · reporting 2s 🌐 248.59 requests/attempt · 1.82 app boots/UI scenario · 0.00% common-shard skew Optimization targets still in progress:
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
|



Detail bug report: View on Detail
Describe your changes:
Fixes #34479
I worked on the Salesforce Data 360 pipeline metadata connector because a failure in any of its three independent listing calls (
get_pipelines_listchained_get_datastreams/_get_calculated_insights/_get_datatransformsvia bareyield from) aborted the remaining listings. The topology runner swallows that producer exception and still runs the root node'spost_process—mark_pipelines_as_deleted— unconditionally, so deletion reconciled against the partialpipeline_source_stateand soft-deleted pipelines whose type was never fetched (worst case: the first listing fails,pipeline_source_stateis empty, and all pipelines under the service are soft-deleted).markDeletedPipelinesdefaults totrue, so this triggers on a normal metadata run.The fix mirrors the mitigation two sibling connectors already use for this exact topology-runner behavior:
_pipeline_listing_completeflag (initialized/ reset toTrueat the start of everyget_pipelines_listrun) tracks whether all listings completed.get_pipelines_listisolates each listing in its owntry/except: on failure it records aStackTraceErrorviastatus.failed, clears the flag, and continues to the next listing instead of aborting the chain.Data360PipelineSourcenow overridesmark_pipelines_as_deletedto skip deletion entirely when the listing was incomplete (logging a warning); otherwise it delegates tosuper(). This is the same pattern as Airflow's_dag_listing_complete(airflow/metadata.py), applied because — like Airflow — this connector deletes by service scope, so a global skip is correct (the Data 360 database sibling uses a per-scope skip since it deletes per schema).Type of change:
High-level design:
N/A — small bug fix (2 files). The approach tracks an already-shipped mitigation pattern (Airflow
_dag_listing_complete), so no new architecture is introduced.Tests:
Use cases covered
pipeline_source_stateis empty.Unit tests
ingestion/tests/unit/topology/pipeline/test_data360pipeline.py— addedTestData360PipelineListingIsolationandTestData360PipelineMarkDeleted(7 tests) covering listing isolation, the incomplete flag (set on failure, reset on the next run, set on a partial yield), and themark_pipelines_as_deletedoverride's skip/delegate branches, plus an end-to-end test that drivesget_pipeline→yield_pipeline→mark_pipelines_as_deletedin topology-runner order with a first-listing failure.make unit_ingestion/pytest -c ingestion/pyproject.toml ingestion/tests/unit/topology/pipeline/test_data360pipeline.py→ 28 passed (21 existing + 7 new). ruff check, ruff format, the ruff-suppressions ratchet, and basedpyright (0 errors) all pass.Backend integration tests
Ingestion integration tests
138ba96b/ PR New feature: Add Salesforce Data360 database and pipeline connectors #31918, present in no release tag), so no published server image knows theData360Pipelineconnection type to run one against. End-to-end behavior was instead verified manually against a real server (below).Playwright (UI) tests
Manual testing performed
docker/docker-compose-quickstart/docker-compose.yml(mysql + elasticsearch + migrations + server); logged in as admin.serviceType=CustomPipeline, since the released server doesn't know the unreleasedData360Pipelinetype) and four pipelines (ds1,ci1,dt1,stale_ds), alldeleted=false. The deletion path under test scopes by service name, so the connection type is irrelevant to it.Data360PipelineSourceproducer →yield_pipelinestage →mark_pipelines_as_deletedpost-process against the live server, spying on the realmetadata.delete_stale_entities(which callsDELETE /pipelines/deleteStale) and reading server-sidedeletedflags via/pipelines/name/<fqn>?include=all.deleteStaleis not called; all four pipelines staydeleted=false(pre-fix,ds1andstale_dswould have been soft-deleted).deleteStaleis called once with the full live set; the genuinely-stalestale_dsis soft-deleted (deleted=true), the live ones staydeleted=false.ds1then raise) →deleteStaleis not called;stale_dsstaysdeleted=false, whileds1was listed before the failure.UI screen recording / screenshots:
Not applicable.
Checklist:
Fixes <issue-number>: <short explanation>Fixes #<issue-number>above.Automatic Fixes PRs can be configured here.