Skip to content

Switch case/default activities are invisible to the parser → undercounted inventory & missing lineage edges #31

Description

@matthewmoorcroft

Summary

parse_activity in src/flowx/parser/adf_loader.py does not parse the activities nested inside an ADF Switch activity (typeProperties.cases[].activities and typeProperties.defaultActivities). Those children never enter the AdfActivity AST, so every downstream consumer that walks the AST is blind to them:

  • Inventory (_classify_activities) undercounts activity_count, coverage_pct, and the strategy/type mix.
  • Lineage (_walk_activities) omits every ExecutePipeline / data edge that lives inside a Switch case.

This affects main (both inventory and lineage are on main).

Why this is a bug, not a design choice (internal contradiction)

flowx's convert/translate layer already reads Switch case children:

  • src/flowx/translator/activity_translators/switch.py iterates type_properties.get("cases")raw_case.get("activities") and recursively translates them, plus defaultActivities.
  • translator/engine.py, bundler/dab_writer.py, and bundler/inner_job_params.py consume them too.

So the tool generates output jobs from Switch-nested activities while never counting them in the inventory or drawing their edges in lineage. One half of the codebase understands the shape; the parse/inventory/lineage half doesn't. parse_activity parses ifTrueActivities/ifFalseActivities (IfCondition) and activities (ForEach/Until) but has no branch for Switch cases — and AdfActivity has no field to hold them. IfCondition and Switch are structurally identical branch containers, so there is no principled reason to parse one and not the other.

Root cause

src/flowx/parser/adf_loader.py, parse_activity (~lines 389-415): parses ifTrueActivities, ifFalseActivities, activities, but never cases[].activities or defaultActivities. AdfActivity (src/flowx/models/adf_ast.py) has if_true_activities / if_false_activities / activities fields but no field for Switch cases.

Impact — quantified on a real 327-pipeline export (a real large factory)

Measured by diffing the raw ADF export against a discover run:

Metric Reported True Gap
activity_count 1,804 ~2,159 355 activities dropped, across 38 pipelines
control edges 591 ~800 209 edges missing (~26% of the true graph)

The 355 hidden activities break down as 216 ExecutePipeline, 89 SetVariable, 44 DatabricksNotebook, 6 Fail. The 216 ExecutePipeline calls are the missing control edges. Notably, app0001_a_pl_orchestrator_main — the core reusable template engine, one of the highest-fan-out pipelines — does its entire fan-out inside a Switch, so it currently appears in lineage as a near-leaf. coverage_pct (reported as 100%) is computed against the undercounted denominator and is therefore not trustworthy for Switch-bearing pipelines.

Steps to reproduce

  1. Run discover on any factory containing a pipeline with a populated Switch (e.g. the existing fixture tests/resources/json/pipelines/pl_test_switch_coverage.json, whose Switch has 3 cases + a default containing DatabricksNotebook and WebActivity children).
  2. Inspect the emitted inventory.json: the Switch's nested activities do not appear in that pipeline's activity list, and any ExecutePipeline inside a case is absent from lineage.control_edges.

Suggested fix

  1. Add a field to AdfActivity for Switch branches (e.g. switch_cases: list[...] | None plus default_activities, or normalize all case/default children into the existing activities list at parse time).
  2. In parse_activity, parse type_properties["cases"][].activities and type_properties["defaultActivities"] into that field.
  3. Have _classify_activities and _walk_activities descend into it (they already recurse via activity.activities, so normalizing into that list is the smallest change).
  4. Regression tests: assert the inventory activity_count for a Switch fixture includes the nested children, and that an ExecutePipeline inside a Switch case produces a control_edges entry.

Notes

  • Fix should branch off main (bug is present there).
  • Independently verified against the raw ADF export and a discover run; numbers above are reproducible, not estimates.

This issue was written by Isaac.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions