-
Notifications
You must be signed in to change notification settings - Fork 15.3k
Feat: Visualize DAG version changes and mixed versions in Grid view #53216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
b3eecb4
to
309e2ea
Compare
09ecc2b
to
bd021e8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! I think this is bringing back the deprecated and removed monolith endpoint with its methods. I think we should integrate the fix into only new structure
cc: @dstandish @pierrejeambrun
@bugraoz93 Thanks for your quick feedback! I saw something strange while fixing the conflict, I think my endpoints follow the old style. I’ll change them to use the new structure. |
Amazing, thanks a lot! |
I’ve updated the tests and removed the old structure, |
I’ve tested the scenarios I had in mind, and everything looks good so far 🙌 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes! I believe this PR still contains old deprecated code :)
return 1 | ||
|
||
|
||
def fill_task_instance_summaries( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is still from old method
|
||
log = structlog.get_logger(logger_name=__name__) | ||
|
||
|
||
def get_task_group_map(dag: DAG) -> dict[str, dict[str, Any]]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This as well
from airflow.models.dag_version import DagVersion | ||
from airflow.models.dagrun import DagRun | ||
from airflow.models.taskinstance import TaskInstance | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if TYPE_CHECKING:
from foo import bar ~~~
how about adding some object which only indicate type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Thanks for the PR!
def __init__(self, session: SessionDep): | ||
self.session = session | ||
|
||
def detect_mixed_versions(self, dag_id: str, dag_run_ids: list[str]) -> dict[str, dict]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about adding DagVersionInfo(TypedDict)
as type annotation for the return type?
unique_version_ids = set(v["version_id"] for v in versions) | ||
has_mixed_versions = len(unique_version_ids) > 1 | ||
|
||
# Get the latest version number if mixed versions exist | ||
latest_version_number = None | ||
if has_mixed_versions: | ||
latest_version_number = max( | ||
v["version_number"] for v in versions if v["version_number"] is not None | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can get the has_mixed_versions
and latest_version_number
in on loop.
|
||
def detect_version_changes( | ||
self, dag_runs: list[DagRun], mixed_versions_info: dict[str, dict] | ||
) -> list[dict]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about adding TypedDict
here for the return type as well ?
I thought I deleted the old version, but it still there. |
If we want to visualize version change, in my opinion, we should do it for bundle version and not dag version that changes everytime especially for dynamic dags cc @jedcunningham |
In that case, we might need to use an icon and then show the bundle version in a tooltip. Maybe something like |
Maybe we need both with different colors, dag version change (to task level) + bundle version change (dag run level only). If we were to keep only one, I would be in favor of keeping the DagVersion because it is consistant with the Graph(Graph is showing structures of specific dag versions), And because I think source code is less important than what was actually executed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the code looks very complicated for what we are trying to achieve. (And also there are some unused stuff I believe from the legacy grid)
The backend need to serialize the dag_run.versions
in the GridRunsResponse
, same for tasks.
And in the UI, we just need a simple logic to check if dag_run.version
of Nth run is equal to dag_run.version
of (N-1)th run.
(Same logic goes for tasks, and yes if DagRun.dag_versions.lenght === 1
no need to go try the task level logic)
Maybe I missed something though.
<Box bg="orange.400" height="2px" left="0" position="absolute" top="-1px" width="18px" zIndex={3}> | ||
<Text | ||
bg="white" | ||
borderRadius="2px" | ||
color="orange.700" | ||
fontSize="8px" | ||
position="absolute" | ||
px="1px" | ||
right="-8px" | ||
top="-4px" | ||
whiteSpace="nowrap" | ||
> | ||
{`v${taskInstance.dag_version_number ?? ""}`} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Horizontal and Vertical version divider should look exactly the same (Background, space between the head and the bar, etc...)
I'm afraid that we can potentially have as many tooltips as TI in the grid. Which would most likely bring back tooltip performance issue we observed in the past. |
Yes, you're right. I missed the Grid part while working on the feature, so I wrote the code based on the old structure 😥 |
Summary
Adds visual indicators in the Grid view to help users identify DAG version changes and detect mixed-version TaskInstances within a single DagRun.
Problem
Solution
This PR introduces visual cues in the Grid view to address these pain points:
Indicator Scenarios
Scenario 1: Normal
Scenario 2: Version Change
Scenario 3: Mixed Version
Scenario 4: Priority Applied
Scenario 5: Complex Pattern
Indicator Position Rules
Priority
Version Change > Mixed Version
Change
Backend
Introduced a new DagVersionService that:
Extended API response models to include:
Frontend
VersionIndicator
component inGrid bars
to display version change and mixed-version status.TaskInstancesColumn.tsx
.Testing
extract_dynamic_fields()
helper for UUID validation and dynamic field extractiondag_version_id
,dag_version_number
,is_version_changed
,has_mixed_versions
closes: #52286
^ Add meaningful description above
Read the Pull Request Guidelines for more information.
In case of fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
In case of a new dependency, check compliance with the ASF 3rd Party License Policy.
In case of backwards incompatible changes please leave a note in a newsfragment file, named
{pr_number}.significant.rst
or{issue_number}.significant.rst
, in airflow-core/newsfragments.