Support for sorting DAGs in the web UI#11652
Conversation
|
Congratulations on your first Pull Request and welcome to the Apache Airflow community! If you have any issues or are unsure about any anything please check our Contribution Guide (https://github.com/apache/airflow/blob/master/CONTRIBUTING.rst)
|
|
/cc @ryanahamilton |
ryanahamilton
left a comment
There was a problem hiding this comment.
This will be a nice update! I believe there used to be a JavaScript implementation of this, but it required the full dataset to be loaded (not paginated) in order to sort properly. Speaking of pagination, I think you need to add sortBy and orderBy arguments to wwwutils.generate_pages() in views.py so those params aren't abandoned on subsequent pages.
|
Nice, I like the changing icons based on the sort state! |
8069a9a to
bc75866
Compare
There was a problem hiding this comment.
It might be easier/less code to have a single sort_by and have this as
| dag_query_key_map = { | |
| 'dag_id': DagModel.dag_id, | |
| 'owner': DagModel.owners, | |
| 'schedule': DagModel.next_dagrun, | |
| # <- add any extra (URL param)->(DagModel attr) mappings here | |
| } | |
| dag_query_key_map = { | |
| 'dag_id': DagModel.dag_id, | |
| '-dag_id': DagModel.dag_id.desc(), | |
| 'owner': DagModel.owners, | |
| '-owner': DagModel.owners.desc(), | |
| 'schedule': DagModel.next_dagrun, | |
| '-schedule': DagModel.next_dagrun.desc(), | |
| # <- add any extra (URL param)->(DagModel attr) mappings here | |
| } |
That way we don't need to have extra sorting_order param. I think this makes the code and the URI simpler. (For instance, query_ordering_transform_for_key wouldn't be needed anymore)
Additionally this order probably doesn't belong in this file -- but instead in the views.py file, probably in the home function.
There was a problem hiding this comment.
(If you think the current way is clearer, tell me. But I do think the location is wrong for this, as it is specific to one particular view.)
There was a problem hiding this comment.
I see your point, but I feel like the suggested way is a bigger PITA from a long-term maintenance perspective - you have to add each new sortable in duplicate. It also seems less intuitive when looking at the URL - the current setup basically just replicates the underlying SQL. All in all, I was trying to make the two bits as independently testable as possible.
I may be getting ahead of myself, but it should also make things easier if someone wanted to sort by multiple columns - e.g. ASC by ID and DESC by owner would be orderBy=asc;desc and then you could just zip() it with sortBy's items.
Re: the module location, point taken. I will move things around as appropriate. I was kind of hoping someone would slap me and point me to the right place if this one wasn't it, so - appreciated!
|
thanks for working on this @scrdest and your first Airflow contribution :) |
bc75866 to
dc67ed0
Compare
|
@scrdest heads up, I've made several recent markup changes to the table in |
dc67ed0 to
8d62206
Compare
8d62206 to
217d26b
Compare
|
@kaxil - rebased. |
ryanahamilton
left a comment
There was a problem hiding this comment.
I pulled this down and tested it locally—it's looking really good. Left a couple suggestions.
aa0be27 to
e79ddbf
Compare
|
The Workflow run is cancelling this PR. It has some failed jobs matching ^Pylint$,^Static checks,^Build docs$,^Spell check docs$,^Backport packages$,^Provider packages,^Checks: Helm tests$,^Test OpenAPI*. |
|
The Workflow run is cancelling this PR. It has some failed jobs matching ^Pylint$,^Static checks,^Build docs$,^Spell check docs$,^Backport packages$,^Provider packages,^Checks: Helm tests$,^Test OpenAPI*. |
|
The Workflow run is cancelling this PR. It has some failed jobs matching ^Pylint$,^Static checks,^Build docs$,^Spell check docs$,^Backport packages$,^Provider packages,^Checks: Helm tests$,^Test OpenAPI*. |
d459503 to
11a7232
Compare
|
The Workflow run is cancelling this PR. It has some failed jobs matching ^Pylint$,^Static checks,^Build docs$,^Spell check docs$,^Backport packages$,^Provider packages,^Checks: Helm tests$,^Test OpenAPI*. |
|
Long thread :) - I think however that one is not critical and can be done in 2.1 ? @ashb @ryanahamilton WDYT? |
…status to the web UI.
…) to views and moved the tests correspondingly.
Co-authored-by: RosterIn <[email protected]>
Co-authored-by: Ryan Hamilton <[email protected]>
…he roles of the two params.
…un" to keep it in line with the underlying attribute.
2de1a14 to
e522fd7
Compare
e522fd7 to
5585e10
Compare
|
@jedcunningham rebased and fixed up where necessary; thanks for the heads-up on view tests! |
jedcunningham
left a comment
There was a problem hiding this comment.
The pagination links also aren't maintaining orderBy and orderDir, but I haven't dug into why. Do they work for you?
| dag_id_query = dag_query_for_key(sorting_key='dag_id') | ||
| dag_id_query_casetest = dag_query_for_key(sorting_key='dAg_Id') | ||
|
|
||
| assert dag_id_query == DagModel.dag_id | ||
| assert dag_id_query_casetest == dag_id_query | ||
|
|
||
| owner_query = dag_query_for_key(sorting_key='owner') | ||
| owner_query_casetest = dag_query_for_key(sorting_key='oWnEr') | ||
|
|
||
| assert owner_query == DagModel.owners | ||
| assert owner_query != dag_id_query | ||
| assert owner_query_casetest == owner_query | ||
|
|
||
| schedule_query = dag_query_for_key(sorting_key='next_dagrun') | ||
|
|
||
| assert schedule_query == DagModel.next_dagrun | ||
| assert schedule_query != dag_id_query | ||
| assert schedule_query != owner_query |
There was a problem hiding this comment.
nit: This whole section could utilize pytest.mark.parameterize which would make it cleaner imo, e.g. (untested):
| dag_id_query = dag_query_for_key(sorting_key='dag_id') | |
| dag_id_query_casetest = dag_query_for_key(sorting_key='dAg_Id') | |
| assert dag_id_query == DagModel.dag_id | |
| assert dag_id_query_casetest == dag_id_query | |
| owner_query = dag_query_for_key(sorting_key='owner') | |
| owner_query_casetest = dag_query_for_key(sorting_key='oWnEr') | |
| assert owner_query == DagModel.owners | |
| assert owner_query != dag_id_query | |
| assert owner_query_casetest == owner_query | |
| schedule_query = dag_query_for_key(sorting_key='next_dagrun') | |
| assert schedule_query == DagModel.next_dagrun | |
| assert schedule_query != dag_id_query | |
| assert schedule_query != owner_query | |
| @pytest.mark.parameterize( | |
| "key, expected_query", | |
| [ | |
| ["dag_id", DagModel.dag_id], | |
| ["dAg_Id", DagModel.dag_id], | |
| ["owner", DagModel.owners], | |
| ["oWnEr", DagModel.owners], | |
| ["next_dagrun", DagModel.next_dagrun], | |
| ["NEXT_DAGRUN", DagModel.next_dagrun], | |
| ] | |
| ) | |
| def test_dag_query_for_key(key, expected_query): | |
| assert dag_query_for_key(sorting_key=key) == expected_query |
The same pattern could be used for query_ordering_transform_for_key and build_dag_sorting_query.
| {% set curr_ordering = ('unsorted' if request.args.get('orderDir') != attr_name else request_ordering ) %} | ||
| {% set new_ordering = ('asc' if request.args.get('orderDir') != attr_name or curr_ordering != 'asc' else 'desc' ) %} |
There was a problem hiding this comment.
| {% set curr_ordering = ('unsorted' if request.args.get('orderDir') != attr_name else request_ordering ) %} | |
| {% set new_ordering = ('asc' if request.args.get('orderDir') != attr_name or curr_ordering != 'asc' else 'desc' ) %} | |
| {% set curr_ordering = ('unsorted' if request.args.get('orderBy') != attr_name else request_ordering ) %} | |
| {% set new_ordering = ('asc' if request.args.get('orderBy') != attr_name or curr_ordering != 'asc' else 'desc' ) %} |
|
@scrdest Can you address the requested changes please |
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 5 days if no further activity occurs. Thank you for your contributions. |
Adds support for sorting DAGs in the UI by the ID, Schedule (next run, really) and Owner, ASC/DESC.
The sorting is done on the DB level and parameterized by two new URL parameters - sortBy for the model attribute & orderBy for the type of ordering (ascending/descending).
The default behavior is to sort by Dag ID and order by ascending, and therefore should not come as a surprise to current users.
The column headings in the DAG view have been turned to hyperlinks that pass the parameters for the sorting. For more predictable UX, when switching before sorting attributes (or when none is passed), clicking on a header will always sort it by ASC first. Clicking on the same header again after the page reloads will toggle it to DESC instead. Visually:
Unfortunately, sorting by the most recently executed run as requested by #8459 is not supported yet. The current options were fairly straightforward to handle since the logic that populates the DAG list currently fetches a set of DagModels - this is just an exercise in filtering. Fetching and sorting DagRuns ran the risk of adding a fair bit of extra processing overhead and complicating the logic.
closes: #8459
Screenshots:


