Feature/cursor pagination task instances UI - #64953

Merged
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui
Apr 20, 2026
Merged

Feature/cursor pagination task instances UI#64953
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui

Conversation

@pierrejeambrun

@pierrejeambrunpierrejeambrun commented Apr 9, 2026

Copy link
Copy Markdown
Member

Replace offset-based pagination with cursor-based pagination for the TaskInstances listing page, leveraging the new cursor API endpoint. Pagination now shows only previous/next buttons without page numbers or total count, which eliminates the expensive COUNT(*) query for large datasets.

Add generic cursor pagination support to DataTable via an optional cursorPagination prop so other tables can adopt it.

Building on top of #64845 to plug the UI on this new cursor based pagination. Default table view is much faster.

Responses are much faster. Currenrly it would take ~60 on main to load.

After

Screenshot 2026-04-09 at 11 45 12Screenshot 2026-04-17 at 15 06 14
Was generative AI tooling used to co-author this PR?
  • [Cursor] Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

@pierrejeambrun

Copy link
Copy Markdown
MemberAuthor

Merge backend first.

@pierrejeambrun
pierrejeambrun marked this pull request as draft April 9, 2026 12:08
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds cursor-based pagination for TaskInstances to avoid expensive COUNT(*) queries and speeds up the default listing UI, while keeping offset pagination for existing endpoints/actions.

Changes:

  • Introduces cursor pagination helpers + API support (cursor, next_cursor, previous_cursor) and response model discrimination via pagination.
  • Updates TaskInstances UI to use cursor pagination and extends DataTable with an optional cursorPagination control.
  • Regenerates OpenAPI client types/services and updates unit tests for the new pagination mode.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds separate cursor/offset task instance collection response models in generated client datamodels.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.pyAdds cursor pagination tests and updates existing assertions to include pagination: "offset".
airflow-core/tests/unit/api_fastapi/common/test_parameters.pyReformats imports to multi-line for readability.
airflow-core/tests/unit/api_fastapi/common/test_cursors.pyAdds unit tests for cursor encode/decode and keyset filter behavior.
airflow-core/src/airflow/ui/src/queries/useClearTaskInstances.tsUpdates types to use the offset response model for clear operations.
airflow-core/src/airflow/ui/src/queries/useClearDagRunDryRun.tsUpdates dry-run clear typing to offset response model.
airflow-core/src/airflow/ui/src/queries/useBulkMarkAsDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/queries/useBulkClearDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsxSwitches listing to cursor pagination and wires next/previous into DataTable.
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/FailedLogs.tsxBroadens prop type to accept unioned task instance listing response.
airflow-core/src/airflow/ui/src/components/DataTable/index.tsRe-exports cursor pagination prop type.
airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsxAdds cursorPagination support with prev/next icon buttons and hides total row count in cursor mode.
airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsxUpdates affected tasks typing to offset response model.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsIntroduces cursor/offset response types and unions GetTaskInstancesResponse.
airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.tsAdds cursor query param and updates docs/return types for updated task instance endpoints.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsAdds OpenAPI schemas for cursor/offset collection responses.
airflow-core/src/airflow/ui/openapi-gen/queries/suspense.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/queries.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.tsUpdates generated prefetch helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.tsUpdates generated ensureQueryData helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/common.tsIncludes cursor in task instance query keys for cache separation.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.pyImplements cursor pagination path and returns discriminated cursor/offset response models.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.pyUpdates clear DAG run response to offset pagination model.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlAdds cursor query param + oneOf cursor/offset response schema with discriminator mapping.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.pySplits cursor/offset responses and defines discriminated union response type.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/common.pyAdds base models for offset/cursor paginated responses.
airflow-core/src/airflow/api_fastapi/common/parameters.pyAdds cached resolution to SortParam and exposes resolved columns for cursor encoding/filtering.
airflow-core/src/airflow/api_fastapi/common/cursors.pyAdds cursor token encoding/decoding and keyset WHERE clause builder.

Comment threadairflow-core/src/airflow/api_fastapi/common/cursors.py Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts Outdated
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a5135d0 to a7f9fddCompareApril 17, 2026 09:16
@pierrejeambrun
pierrejeambrun marked this pull request as ready for review April 17, 2026 09:17
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a7f9fdd to c2a34e6CompareApril 17, 2026 09:52
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 3 times, most recently from 9a9ebb5 to 57c751eCompareApril 17, 2026 13:04
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 2 times, most recently from 8b8e080 to c756e41CompareApril 17, 2026 13:47
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from c756e41 to 674dbdbCompareApril 17, 2026 13:54

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, just one question we can solve later

@bbovenzi
bbovenzi merged commit 44ae2bc into apache:mainApr 20, 2026
80 checks passed
@bbovenzi
bbovenzi deleted the feature/cursor-pagination-task-instances-ui branch April 20, 2026 14:15
@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.2 milestone Apr 20, 2026
pierrejeambrun added a commit to astronomer/airflow that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
pierrejeambrun added a commit that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Feature/cursor pagination task instances UI - #64953

Merged
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui
Apr 20, 2026
Merged

Feature/cursor pagination task instances UI#64953
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui

Conversation

@pierrejeambrun

@pierrejeambrunpierrejeambrun commented Apr 9, 2026

Copy link
Copy Markdown
Member

Replace offset-based pagination with cursor-based pagination for the TaskInstances listing page, leveraging the new cursor API endpoint. Pagination now shows only previous/next buttons without page numbers or total count, which eliminates the expensive COUNT(*) query for large datasets.

Add generic cursor pagination support to DataTable via an optional cursorPagination prop so other tables can adopt it.

Building on top of #64845 to plug the UI on this new cursor based pagination. Default table view is much faster.

Responses are much faster. Currenrly it would take ~60 on main to load.

After

Screenshot 2026-04-09 at 11 45 12Screenshot 2026-04-17 at 15 06 14
Was generative AI tooling used to co-author this PR?
  • [Cursor] Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

@pierrejeambrun

Copy link
Copy Markdown
MemberAuthor

Merge backend first.

@pierrejeambrun
pierrejeambrun marked this pull request as draft April 9, 2026 12:08
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds cursor-based pagination for TaskInstances to avoid expensive COUNT(*) queries and speeds up the default listing UI, while keeping offset pagination for existing endpoints/actions.

Changes:

  • Introduces cursor pagination helpers + API support (cursor, next_cursor, previous_cursor) and response model discrimination via pagination.
  • Updates TaskInstances UI to use cursor pagination and extends DataTable with an optional cursorPagination control.
  • Regenerates OpenAPI client types/services and updates unit tests for the new pagination mode.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds separate cursor/offset task instance collection response models in generated client datamodels.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.pyAdds cursor pagination tests and updates existing assertions to include pagination: "offset".
airflow-core/tests/unit/api_fastapi/common/test_parameters.pyReformats imports to multi-line for readability.
airflow-core/tests/unit/api_fastapi/common/test_cursors.pyAdds unit tests for cursor encode/decode and keyset filter behavior.
airflow-core/src/airflow/ui/src/queries/useClearTaskInstances.tsUpdates types to use the offset response model for clear operations.
airflow-core/src/airflow/ui/src/queries/useClearDagRunDryRun.tsUpdates dry-run clear typing to offset response model.
airflow-core/src/airflow/ui/src/queries/useBulkMarkAsDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/queries/useBulkClearDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsxSwitches listing to cursor pagination and wires next/previous into DataTable.
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/FailedLogs.tsxBroadens prop type to accept unioned task instance listing response.
airflow-core/src/airflow/ui/src/components/DataTable/index.tsRe-exports cursor pagination prop type.
airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsxAdds cursorPagination support with prev/next icon buttons and hides total row count in cursor mode.
airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsxUpdates affected tasks typing to offset response model.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsIntroduces cursor/offset response types and unions GetTaskInstancesResponse.
airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.tsAdds cursor query param and updates docs/return types for updated task instance endpoints.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsAdds OpenAPI schemas for cursor/offset collection responses.
airflow-core/src/airflow/ui/openapi-gen/queries/suspense.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/queries.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.tsUpdates generated prefetch helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.tsUpdates generated ensureQueryData helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/common.tsIncludes cursor in task instance query keys for cache separation.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.pyImplements cursor pagination path and returns discriminated cursor/offset response models.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.pyUpdates clear DAG run response to offset pagination model.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlAdds cursor query param + oneOf cursor/offset response schema with discriminator mapping.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.pySplits cursor/offset responses and defines discriminated union response type.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/common.pyAdds base models for offset/cursor paginated responses.
airflow-core/src/airflow/api_fastapi/common/parameters.pyAdds cached resolution to SortParam and exposes resolved columns for cursor encoding/filtering.
airflow-core/src/airflow/api_fastapi/common/cursors.pyAdds cursor token encoding/decoding and keyset WHERE clause builder.

Comment threadairflow-core/src/airflow/api_fastapi/common/cursors.py Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts Outdated
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a5135d0 to a7f9fddCompareApril 17, 2026 09:16
@pierrejeambrun
pierrejeambrun marked this pull request as ready for review April 17, 2026 09:17
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a7f9fdd to c2a34e6CompareApril 17, 2026 09:52
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 3 times, most recently from 9a9ebb5 to 57c751eCompareApril 17, 2026 13:04
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 2 times, most recently from 8b8e080 to c756e41CompareApril 17, 2026 13:47
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from c756e41 to 674dbdbCompareApril 17, 2026 13:54

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, just one question we can solve later

@bbovenzi
bbovenzi merged commit 44ae2bc into apache:mainApr 20, 2026
80 checks passed
@bbovenzi
bbovenzi deleted the feature/cursor-pagination-task-instances-ui branch April 20, 2026 14:15
@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.2 milestone Apr 20, 2026
pierrejeambrun added a commit to astronomer/airflow that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
pierrejeambrun added a commit that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Feature/cursor pagination task instances UI - #64953

Merged
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui
Apr 20, 2026
Merged

Feature/cursor pagination task instances UI#64953
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui

Conversation

@pierrejeambrun

@pierrejeambrunpierrejeambrun commented Apr 9, 2026

Copy link
Copy Markdown
Member

Replace offset-based pagination with cursor-based pagination for the TaskInstances listing page, leveraging the new cursor API endpoint. Pagination now shows only previous/next buttons without page numbers or total count, which eliminates the expensive COUNT(*) query for large datasets.

Add generic cursor pagination support to DataTable via an optional cursorPagination prop so other tables can adopt it.

Building on top of #64845 to plug the UI on this new cursor based pagination. Default table view is much faster.

Responses are much faster. Currenrly it would take ~60 on main to load.

After

Screenshot 2026-04-09 at 11 45 12Screenshot 2026-04-17 at 15 06 14
Was generative AI tooling used to co-author this PR?
  • [Cursor] Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

@pierrejeambrun

Copy link
Copy Markdown
MemberAuthor

Merge backend first.

@pierrejeambrun
pierrejeambrun marked this pull request as draft April 9, 2026 12:08
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds cursor-based pagination for TaskInstances to avoid expensive COUNT(*) queries and speeds up the default listing UI, while keeping offset pagination for existing endpoints/actions.

Changes:

  • Introduces cursor pagination helpers + API support (cursor, next_cursor, previous_cursor) and response model discrimination via pagination.
  • Updates TaskInstances UI to use cursor pagination and extends DataTable with an optional cursorPagination control.
  • Regenerates OpenAPI client types/services and updates unit tests for the new pagination mode.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds separate cursor/offset task instance collection response models in generated client datamodels.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.pyAdds cursor pagination tests and updates existing assertions to include pagination: "offset".
airflow-core/tests/unit/api_fastapi/common/test_parameters.pyReformats imports to multi-line for readability.
airflow-core/tests/unit/api_fastapi/common/test_cursors.pyAdds unit tests for cursor encode/decode and keyset filter behavior.
airflow-core/src/airflow/ui/src/queries/useClearTaskInstances.tsUpdates types to use the offset response model for clear operations.
airflow-core/src/airflow/ui/src/queries/useClearDagRunDryRun.tsUpdates dry-run clear typing to offset response model.
airflow-core/src/airflow/ui/src/queries/useBulkMarkAsDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/queries/useBulkClearDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsxSwitches listing to cursor pagination and wires next/previous into DataTable.
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/FailedLogs.tsxBroadens prop type to accept unioned task instance listing response.
airflow-core/src/airflow/ui/src/components/DataTable/index.tsRe-exports cursor pagination prop type.
airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsxAdds cursorPagination support with prev/next icon buttons and hides total row count in cursor mode.
airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsxUpdates affected tasks typing to offset response model.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsIntroduces cursor/offset response types and unions GetTaskInstancesResponse.
airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.tsAdds cursor query param and updates docs/return types for updated task instance endpoints.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsAdds OpenAPI schemas for cursor/offset collection responses.
airflow-core/src/airflow/ui/openapi-gen/queries/suspense.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/queries.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.tsUpdates generated prefetch helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.tsUpdates generated ensureQueryData helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/common.tsIncludes cursor in task instance query keys for cache separation.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.pyImplements cursor pagination path and returns discriminated cursor/offset response models.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.pyUpdates clear DAG run response to offset pagination model.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlAdds cursor query param + oneOf cursor/offset response schema with discriminator mapping.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.pySplits cursor/offset responses and defines discriminated union response type.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/common.pyAdds base models for offset/cursor paginated responses.
airflow-core/src/airflow/api_fastapi/common/parameters.pyAdds cached resolution to SortParam and exposes resolved columns for cursor encoding/filtering.
airflow-core/src/airflow/api_fastapi/common/cursors.pyAdds cursor token encoding/decoding and keyset WHERE clause builder.

Comment threadairflow-core/src/airflow/api_fastapi/common/cursors.py Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts Outdated
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a5135d0 to a7f9fddCompareApril 17, 2026 09:16
@pierrejeambrun
pierrejeambrun marked this pull request as ready for review April 17, 2026 09:17
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a7f9fdd to c2a34e6CompareApril 17, 2026 09:52
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 3 times, most recently from 9a9ebb5 to 57c751eCompareApril 17, 2026 13:04
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 2 times, most recently from 8b8e080 to c756e41CompareApril 17, 2026 13:47
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from c756e41 to 674dbdbCompareApril 17, 2026 13:54

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, just one question we can solve later

@bbovenzi
bbovenzi merged commit 44ae2bc into apache:mainApr 20, 2026
80 checks passed
@bbovenzi
bbovenzi deleted the feature/cursor-pagination-task-instances-ui branch April 20, 2026 14:15
@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.2 milestone Apr 20, 2026
pierrejeambrun added a commit to astronomer/airflow that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
pierrejeambrun added a commit that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Feature/cursor pagination task instances UI - #64953

Merged
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui
Apr 20, 2026
Merged

Feature/cursor pagination task instances UI#64953
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui

Conversation

@pierrejeambrun

@pierrejeambrunpierrejeambrun commented Apr 9, 2026

Copy link
Copy Markdown
Member

Replace offset-based pagination with cursor-based pagination for the TaskInstances listing page, leveraging the new cursor API endpoint. Pagination now shows only previous/next buttons without page numbers or total count, which eliminates the expensive COUNT(*) query for large datasets.

Add generic cursor pagination support to DataTable via an optional cursorPagination prop so other tables can adopt it.

Building on top of #64845 to plug the UI on this new cursor based pagination. Default table view is much faster.

Responses are much faster. Currenrly it would take ~60 on main to load.

After

Screenshot 2026-04-09 at 11 45 12Screenshot 2026-04-17 at 15 06 14
Was generative AI tooling used to co-author this PR?
  • [Cursor] Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

@pierrejeambrun

Copy link
Copy Markdown
MemberAuthor

Merge backend first.

@pierrejeambrun
pierrejeambrun marked this pull request as draft April 9, 2026 12:08
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds cursor-based pagination for TaskInstances to avoid expensive COUNT(*) queries and speeds up the default listing UI, while keeping offset pagination for existing endpoints/actions.

Changes:

  • Introduces cursor pagination helpers + API support (cursor, next_cursor, previous_cursor) and response model discrimination via pagination.
  • Updates TaskInstances UI to use cursor pagination and extends DataTable with an optional cursorPagination control.
  • Regenerates OpenAPI client types/services and updates unit tests for the new pagination mode.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds separate cursor/offset task instance collection response models in generated client datamodels.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.pyAdds cursor pagination tests and updates existing assertions to include pagination: "offset".
airflow-core/tests/unit/api_fastapi/common/test_parameters.pyReformats imports to multi-line for readability.
airflow-core/tests/unit/api_fastapi/common/test_cursors.pyAdds unit tests for cursor encode/decode and keyset filter behavior.
airflow-core/src/airflow/ui/src/queries/useClearTaskInstances.tsUpdates types to use the offset response model for clear operations.
airflow-core/src/airflow/ui/src/queries/useClearDagRunDryRun.tsUpdates dry-run clear typing to offset response model.
airflow-core/src/airflow/ui/src/queries/useBulkMarkAsDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/queries/useBulkClearDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsxSwitches listing to cursor pagination and wires next/previous into DataTable.
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/FailedLogs.tsxBroadens prop type to accept unioned task instance listing response.
airflow-core/src/airflow/ui/src/components/DataTable/index.tsRe-exports cursor pagination prop type.
airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsxAdds cursorPagination support with prev/next icon buttons and hides total row count in cursor mode.
airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsxUpdates affected tasks typing to offset response model.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsIntroduces cursor/offset response types and unions GetTaskInstancesResponse.
airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.tsAdds cursor query param and updates docs/return types for updated task instance endpoints.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsAdds OpenAPI schemas for cursor/offset collection responses.
airflow-core/src/airflow/ui/openapi-gen/queries/suspense.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/queries.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.tsUpdates generated prefetch helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.tsUpdates generated ensureQueryData helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/common.tsIncludes cursor in task instance query keys for cache separation.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.pyImplements cursor pagination path and returns discriminated cursor/offset response models.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.pyUpdates clear DAG run response to offset pagination model.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlAdds cursor query param + oneOf cursor/offset response schema with discriminator mapping.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.pySplits cursor/offset responses and defines discriminated union response type.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/common.pyAdds base models for offset/cursor paginated responses.
airflow-core/src/airflow/api_fastapi/common/parameters.pyAdds cached resolution to SortParam and exposes resolved columns for cursor encoding/filtering.
airflow-core/src/airflow/api_fastapi/common/cursors.pyAdds cursor token encoding/decoding and keyset WHERE clause builder.

Comment threadairflow-core/src/airflow/api_fastapi/common/cursors.py Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts Outdated
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a5135d0 to a7f9fddCompareApril 17, 2026 09:16
@pierrejeambrun
pierrejeambrun marked this pull request as ready for review April 17, 2026 09:17
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a7f9fdd to c2a34e6CompareApril 17, 2026 09:52
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 3 times, most recently from 9a9ebb5 to 57c751eCompareApril 17, 2026 13:04
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 2 times, most recently from 8b8e080 to c756e41CompareApril 17, 2026 13:47
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from c756e41 to 674dbdbCompareApril 17, 2026 13:54

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, just one question we can solve later

@bbovenzi
bbovenzi merged commit 44ae2bc into apache:mainApr 20, 2026
80 checks passed
@bbovenzi
bbovenzi deleted the feature/cursor-pagination-task-instances-ui branch April 20, 2026 14:15
@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.2 milestone Apr 20, 2026
pierrejeambrun added a commit to astronomer/airflow that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
pierrejeambrun added a commit that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Feature/cursor pagination task instances UI - #64953

Merged
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui
Apr 20, 2026
Merged

Feature/cursor pagination task instances UI#64953
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui

Conversation

@pierrejeambrun

@pierrejeambrunpierrejeambrun commented Apr 9, 2026

Copy link
Copy Markdown
Member

Replace offset-based pagination with cursor-based pagination for the TaskInstances listing page, leveraging the new cursor API endpoint. Pagination now shows only previous/next buttons without page numbers or total count, which eliminates the expensive COUNT(*) query for large datasets.

Add generic cursor pagination support to DataTable via an optional cursorPagination prop so other tables can adopt it.

Building on top of #64845 to plug the UI on this new cursor based pagination. Default table view is much faster.

Responses are much faster. Currenrly it would take ~60 on main to load.

After

Screenshot 2026-04-09 at 11 45 12Screenshot 2026-04-17 at 15 06 14
Was generative AI tooling used to co-author this PR?
  • [Cursor] Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

@pierrejeambrun

Copy link
Copy Markdown
MemberAuthor

Merge backend first.

@pierrejeambrun
pierrejeambrun marked this pull request as draft April 9, 2026 12:08
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds cursor-based pagination for TaskInstances to avoid expensive COUNT(*) queries and speeds up the default listing UI, while keeping offset pagination for existing endpoints/actions.

Changes:

  • Introduces cursor pagination helpers + API support (cursor, next_cursor, previous_cursor) and response model discrimination via pagination.
  • Updates TaskInstances UI to use cursor pagination and extends DataTable with an optional cursorPagination control.
  • Regenerates OpenAPI client types/services and updates unit tests for the new pagination mode.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds separate cursor/offset task instance collection response models in generated client datamodels.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.pyAdds cursor pagination tests and updates existing assertions to include pagination: "offset".
airflow-core/tests/unit/api_fastapi/common/test_parameters.pyReformats imports to multi-line for readability.
airflow-core/tests/unit/api_fastapi/common/test_cursors.pyAdds unit tests for cursor encode/decode and keyset filter behavior.
airflow-core/src/airflow/ui/src/queries/useClearTaskInstances.tsUpdates types to use the offset response model for clear operations.
airflow-core/src/airflow/ui/src/queries/useClearDagRunDryRun.tsUpdates dry-run clear typing to offset response model.
airflow-core/src/airflow/ui/src/queries/useBulkMarkAsDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/queries/useBulkClearDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsxSwitches listing to cursor pagination and wires next/previous into DataTable.
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/FailedLogs.tsxBroadens prop type to accept unioned task instance listing response.
airflow-core/src/airflow/ui/src/components/DataTable/index.tsRe-exports cursor pagination prop type.
airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsxAdds cursorPagination support with prev/next icon buttons and hides total row count in cursor mode.
airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsxUpdates affected tasks typing to offset response model.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsIntroduces cursor/offset response types and unions GetTaskInstancesResponse.
airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.tsAdds cursor query param and updates docs/return types for updated task instance endpoints.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsAdds OpenAPI schemas for cursor/offset collection responses.
airflow-core/src/airflow/ui/openapi-gen/queries/suspense.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/queries.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.tsUpdates generated prefetch helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.tsUpdates generated ensureQueryData helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/common.tsIncludes cursor in task instance query keys for cache separation.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.pyImplements cursor pagination path and returns discriminated cursor/offset response models.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.pyUpdates clear DAG run response to offset pagination model.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlAdds cursor query param + oneOf cursor/offset response schema with discriminator mapping.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.pySplits cursor/offset responses and defines discriminated union response type.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/common.pyAdds base models for offset/cursor paginated responses.
airflow-core/src/airflow/api_fastapi/common/parameters.pyAdds cached resolution to SortParam and exposes resolved columns for cursor encoding/filtering.
airflow-core/src/airflow/api_fastapi/common/cursors.pyAdds cursor token encoding/decoding and keyset WHERE clause builder.

Comment threadairflow-core/src/airflow/api_fastapi/common/cursors.py Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts Outdated
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a5135d0 to a7f9fddCompareApril 17, 2026 09:16
@pierrejeambrun
pierrejeambrun marked this pull request as ready for review April 17, 2026 09:17
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a7f9fdd to c2a34e6CompareApril 17, 2026 09:52
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 3 times, most recently from 9a9ebb5 to 57c751eCompareApril 17, 2026 13:04
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 2 times, most recently from 8b8e080 to c756e41CompareApril 17, 2026 13:47
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from c756e41 to 674dbdbCompareApril 17, 2026 13:54

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, just one question we can solve later

@bbovenzi
bbovenzi merged commit 44ae2bc into apache:mainApr 20, 2026
80 checks passed
@bbovenzi
bbovenzi deleted the feature/cursor-pagination-task-instances-ui branch April 20, 2026 14:15
@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.2 milestone Apr 20, 2026
pierrejeambrun added a commit to astronomer/airflow that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
pierrejeambrun added a commit that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Feature/cursor pagination task instances UI - #64953

Merged
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui
Apr 20, 2026
Merged

Feature/cursor pagination task instances UI#64953
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui

Conversation

@pierrejeambrun

@pierrejeambrunpierrejeambrun commented Apr 9, 2026

Copy link
Copy Markdown
Member

Replace offset-based pagination with cursor-based pagination for the TaskInstances listing page, leveraging the new cursor API endpoint. Pagination now shows only previous/next buttons without page numbers or total count, which eliminates the expensive COUNT(*) query for large datasets.

Add generic cursor pagination support to DataTable via an optional cursorPagination prop so other tables can adopt it.

Building on top of #64845 to plug the UI on this new cursor based pagination. Default table view is much faster.

Responses are much faster. Currenrly it would take ~60 on main to load.

After

Screenshot 2026-04-09 at 11 45 12Screenshot 2026-04-17 at 15 06 14
Was generative AI tooling used to co-author this PR?
  • [Cursor] Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

@pierrejeambrun

Copy link
Copy Markdown
MemberAuthor

Merge backend first.

@pierrejeambrun
pierrejeambrun marked this pull request as draft April 9, 2026 12:08
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds cursor-based pagination for TaskInstances to avoid expensive COUNT(*) queries and speeds up the default listing UI, while keeping offset pagination for existing endpoints/actions.

Changes:

  • Introduces cursor pagination helpers + API support (cursor, next_cursor, previous_cursor) and response model discrimination via pagination.
  • Updates TaskInstances UI to use cursor pagination and extends DataTable with an optional cursorPagination control.
  • Regenerates OpenAPI client types/services and updates unit tests for the new pagination mode.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds separate cursor/offset task instance collection response models in generated client datamodels.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.pyAdds cursor pagination tests and updates existing assertions to include pagination: "offset".
airflow-core/tests/unit/api_fastapi/common/test_parameters.pyReformats imports to multi-line for readability.
airflow-core/tests/unit/api_fastapi/common/test_cursors.pyAdds unit tests for cursor encode/decode and keyset filter behavior.
airflow-core/src/airflow/ui/src/queries/useClearTaskInstances.tsUpdates types to use the offset response model for clear operations.
airflow-core/src/airflow/ui/src/queries/useClearDagRunDryRun.tsUpdates dry-run clear typing to offset response model.
airflow-core/src/airflow/ui/src/queries/useBulkMarkAsDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/queries/useBulkClearDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsxSwitches listing to cursor pagination and wires next/previous into DataTable.
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/FailedLogs.tsxBroadens prop type to accept unioned task instance listing response.
airflow-core/src/airflow/ui/src/components/DataTable/index.tsRe-exports cursor pagination prop type.
airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsxAdds cursorPagination support with prev/next icon buttons and hides total row count in cursor mode.
airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsxUpdates affected tasks typing to offset response model.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsIntroduces cursor/offset response types and unions GetTaskInstancesResponse.
airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.tsAdds cursor query param and updates docs/return types for updated task instance endpoints.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsAdds OpenAPI schemas for cursor/offset collection responses.
airflow-core/src/airflow/ui/openapi-gen/queries/suspense.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/queries.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.tsUpdates generated prefetch helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.tsUpdates generated ensureQueryData helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/common.tsIncludes cursor in task instance query keys for cache separation.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.pyImplements cursor pagination path and returns discriminated cursor/offset response models.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.pyUpdates clear DAG run response to offset pagination model.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlAdds cursor query param + oneOf cursor/offset response schema with discriminator mapping.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.pySplits cursor/offset responses and defines discriminated union response type.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/common.pyAdds base models for offset/cursor paginated responses.
airflow-core/src/airflow/api_fastapi/common/parameters.pyAdds cached resolution to SortParam and exposes resolved columns for cursor encoding/filtering.
airflow-core/src/airflow/api_fastapi/common/cursors.pyAdds cursor token encoding/decoding and keyset WHERE clause builder.

Comment threadairflow-core/src/airflow/api_fastapi/common/cursors.py Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts Outdated
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a5135d0 to a7f9fddCompareApril 17, 2026 09:16
@pierrejeambrun
pierrejeambrun marked this pull request as ready for review April 17, 2026 09:17
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a7f9fdd to c2a34e6CompareApril 17, 2026 09:52
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 3 times, most recently from 9a9ebb5 to 57c751eCompareApril 17, 2026 13:04
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 2 times, most recently from 8b8e080 to c756e41CompareApril 17, 2026 13:47
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from c756e41 to 674dbdbCompareApril 17, 2026 13:54

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, just one question we can solve later

@bbovenzi
bbovenzi merged commit 44ae2bc into apache:mainApr 20, 2026
80 checks passed
@bbovenzi
bbovenzi deleted the feature/cursor-pagination-task-instances-ui branch April 20, 2026 14:15
@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.2 milestone Apr 20, 2026
pierrejeambrun added a commit to astronomer/airflow that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
pierrejeambrun added a commit that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Feature/cursor pagination task instances UI - #64953

Merged
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui
Apr 20, 2026
Merged

Feature/cursor pagination task instances UI#64953
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui

Conversation

@pierrejeambrun

@pierrejeambrunpierrejeambrun commented Apr 9, 2026

Copy link
Copy Markdown
Member

Replace offset-based pagination with cursor-based pagination for the TaskInstances listing page, leveraging the new cursor API endpoint. Pagination now shows only previous/next buttons without page numbers or total count, which eliminates the expensive COUNT(*) query for large datasets.

Add generic cursor pagination support to DataTable via an optional cursorPagination prop so other tables can adopt it.

Building on top of #64845 to plug the UI on this new cursor based pagination. Default table view is much faster.

Responses are much faster. Currenrly it would take ~60 on main to load.

After

Screenshot 2026-04-09 at 11 45 12Screenshot 2026-04-17 at 15 06 14
Was generative AI tooling used to co-author this PR?
  • [Cursor] Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

@pierrejeambrun

Copy link
Copy Markdown
MemberAuthor

Merge backend first.

@pierrejeambrun
pierrejeambrun marked this pull request as draft April 9, 2026 12:08
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds cursor-based pagination for TaskInstances to avoid expensive COUNT(*) queries and speeds up the default listing UI, while keeping offset pagination for existing endpoints/actions.

Changes:

  • Introduces cursor pagination helpers + API support (cursor, next_cursor, previous_cursor) and response model discrimination via pagination.
  • Updates TaskInstances UI to use cursor pagination and extends DataTable with an optional cursorPagination control.
  • Regenerates OpenAPI client types/services and updates unit tests for the new pagination mode.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds separate cursor/offset task instance collection response models in generated client datamodels.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.pyAdds cursor pagination tests and updates existing assertions to include pagination: "offset".
airflow-core/tests/unit/api_fastapi/common/test_parameters.pyReformats imports to multi-line for readability.
airflow-core/tests/unit/api_fastapi/common/test_cursors.pyAdds unit tests for cursor encode/decode and keyset filter behavior.
airflow-core/src/airflow/ui/src/queries/useClearTaskInstances.tsUpdates types to use the offset response model for clear operations.
airflow-core/src/airflow/ui/src/queries/useClearDagRunDryRun.tsUpdates dry-run clear typing to offset response model.
airflow-core/src/airflow/ui/src/queries/useBulkMarkAsDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/queries/useBulkClearDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsxSwitches listing to cursor pagination and wires next/previous into DataTable.
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/FailedLogs.tsxBroadens prop type to accept unioned task instance listing response.
airflow-core/src/airflow/ui/src/components/DataTable/index.tsRe-exports cursor pagination prop type.
airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsxAdds cursorPagination support with prev/next icon buttons and hides total row count in cursor mode.
airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsxUpdates affected tasks typing to offset response model.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsIntroduces cursor/offset response types and unions GetTaskInstancesResponse.
airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.tsAdds cursor query param and updates docs/return types for updated task instance endpoints.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsAdds OpenAPI schemas for cursor/offset collection responses.
airflow-core/src/airflow/ui/openapi-gen/queries/suspense.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/queries.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.tsUpdates generated prefetch helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.tsUpdates generated ensureQueryData helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/common.tsIncludes cursor in task instance query keys for cache separation.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.pyImplements cursor pagination path and returns discriminated cursor/offset response models.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.pyUpdates clear DAG run response to offset pagination model.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlAdds cursor query param + oneOf cursor/offset response schema with discriminator mapping.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.pySplits cursor/offset responses and defines discriminated union response type.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/common.pyAdds base models for offset/cursor paginated responses.
airflow-core/src/airflow/api_fastapi/common/parameters.pyAdds cached resolution to SortParam and exposes resolved columns for cursor encoding/filtering.
airflow-core/src/airflow/api_fastapi/common/cursors.pyAdds cursor token encoding/decoding and keyset WHERE clause builder.

Comment threadairflow-core/src/airflow/api_fastapi/common/cursors.py Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts Outdated
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a5135d0 to a7f9fddCompareApril 17, 2026 09:16
@pierrejeambrun
pierrejeambrun marked this pull request as ready for review April 17, 2026 09:17
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a7f9fdd to c2a34e6CompareApril 17, 2026 09:52
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 3 times, most recently from 9a9ebb5 to 57c751eCompareApril 17, 2026 13:04
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 2 times, most recently from 8b8e080 to c756e41CompareApril 17, 2026 13:47
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from c756e41 to 674dbdbCompareApril 17, 2026 13:54

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, just one question we can solve later

@bbovenzi
bbovenzi merged commit 44ae2bc into apache:mainApr 20, 2026
80 checks passed
@bbovenzi
bbovenzi deleted the feature/cursor-pagination-task-instances-ui branch April 20, 2026 14:15
@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.2 milestone Apr 20, 2026
pierrejeambrun added a commit to astronomer/airflow that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
pierrejeambrun added a commit that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pierrejeambrun@bbovenzi
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Feature/cursor pagination task instances UI - #64953

Merged
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui
Apr 20, 2026
Merged

Feature/cursor pagination task instances UI#64953
bbovenzi merged 5 commits into
apache:mainfrom
astronomer:feature/cursor-pagination-task-instances-ui

Conversation

@pierrejeambrun

@pierrejeambrunpierrejeambrun commented Apr 9, 2026

Copy link
Copy Markdown
Member

Replace offset-based pagination with cursor-based pagination for the TaskInstances listing page, leveraging the new cursor API endpoint. Pagination now shows only previous/next buttons without page numbers or total count, which eliminates the expensive COUNT(*) query for large datasets.

Add generic cursor pagination support to DataTable via an optional cursorPagination prop so other tables can adopt it.

Building on top of #64845 to plug the UI on this new cursor based pagination. Default table view is much faster.

Responses are much faster. Currenrly it would take ~60 on main to load.

After

Screenshot 2026-04-09 at 11 45 12Screenshot 2026-04-17 at 15 06 14
Was generative AI tooling used to co-author this PR?
  • [Cursor] Yes (please specify the tool below)

  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.

@pierrejeambrun

Copy link
Copy Markdown
MemberAuthor

Merge backend first.

@pierrejeambrun
pierrejeambrun marked this pull request as draft April 9, 2026 12:08
@kaxil
kaxil requested a review from CopilotApril 10, 2026 19:55

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds cursor-based pagination for TaskInstances to avoid expensive COUNT(*) queries and speeds up the default listing UI, while keeping offset pagination for existing endpoints/actions.

Changes:

  • Introduces cursor pagination helpers + API support (cursor, next_cursor, previous_cursor) and response model discrimination via pagination.
  • Updates TaskInstances UI to use cursor pagination and extends DataTable with an optional cursorPagination control.
  • Regenerates OpenAPI client types/services and updates unit tests for the new pagination mode.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
FileDescription
airflow-ctl/src/airflowctl/api/datamodels/generated.pyAdds separate cursor/offset task instance collection response models in generated client datamodels.
airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_task_instances.pyAdds cursor pagination tests and updates existing assertions to include pagination: "offset".
airflow-core/tests/unit/api_fastapi/common/test_parameters.pyReformats imports to multi-line for readability.
airflow-core/tests/unit/api_fastapi/common/test_cursors.pyAdds unit tests for cursor encode/decode and keyset filter behavior.
airflow-core/src/airflow/ui/src/queries/useClearTaskInstances.tsUpdates types to use the offset response model for clear operations.
airflow-core/src/airflow/ui/src/queries/useClearDagRunDryRun.tsUpdates dry-run clear typing to offset response model.
airflow-core/src/airflow/ui/src/queries/useBulkMarkAsDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/queries/useBulkClearDryRun.tsUpdates response typing and EMPTY constant to offset model.
airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsxSwitches listing to cursor pagination and wires next/previous into DataTable.
airflow-core/src/airflow/ui/src/pages/Task/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsxMakes failed-task count robust to unioned cursor/offset responses.
airflow-core/src/airflow/ui/src/pages/Dag/Overview/FailedLogs.tsxBroadens prop type to accept unioned task instance listing response.
airflow-core/src/airflow/ui/src/components/DataTable/index.tsRe-exports cursor pagination prop type.
airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsxAdds cursorPagination support with prev/next icon buttons and hides total row count in cursor mode.
airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsxUpdates affected tasks typing to offset response model.
airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.tsIntroduces cursor/offset response types and unions GetTaskInstancesResponse.
airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.tsAdds cursor query param and updates docs/return types for updated task instance endpoints.
airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.tsAdds OpenAPI schemas for cursor/offset collection responses.
airflow-core/src/airflow/ui/openapi-gen/queries/suspense.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/queries.tsUpdates generated query hook typing/docs for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.tsUpdates generated prefetch helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.tsUpdates generated ensureQueryData helpers for task instance endpoints with cursor support.
airflow-core/src/airflow/ui/openapi-gen/queries/common.tsIncludes cursor in task instance query keys for cache separation.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/task_instances.pyImplements cursor pagination path and returns discriminated cursor/offset response models.
airflow-core/src/airflow/api_fastapi/core_api/routes/public/dag_run.pyUpdates clear DAG run response to offset pagination model.
airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yamlAdds cursor query param + oneOf cursor/offset response schema with discriminator mapping.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/task_instances.pySplits cursor/offset responses and defines discriminated union response type.
airflow-core/src/airflow/api_fastapi/core_api/datamodels/common.pyAdds base models for offset/cursor paginated responses.
airflow-core/src/airflow/api_fastapi/common/parameters.pyAdds cached resolution to SortParam and exposes resolved columns for cursor encoding/filtering.
airflow-core/src/airflow/api_fastapi/common/cursors.pyAdds cursor token encoding/decoding and keyset WHERE clause builder.

Comment threadairflow-core/src/airflow/api_fastapi/common/cursors.py Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts Outdated
Comment threadairflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts Outdated
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a5135d0 to a7f9fddCompareApril 17, 2026 09:16
@pierrejeambrun
pierrejeambrun marked this pull request as ready for review April 17, 2026 09:17
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from a7f9fdd to c2a34e6CompareApril 17, 2026 09:52
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 3 times, most recently from 9a9ebb5 to 57c751eCompareApril 17, 2026 13:04
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch 2 times, most recently from 8b8e080 to c756e41CompareApril 17, 2026 13:47
@pierrejeambrun
pierrejeambrunforce-pushed the feature/cursor-pagination-task-instances-ui branch from c756e41 to 674dbdbCompareApril 17, 2026 13:54

@bbovenzibbovenzi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm, just one question we can solve later

@bbovenzi
bbovenzi merged commit 44ae2bc into apache:mainApr 20, 2026
80 checks passed
@bbovenzi
bbovenzi deleted the feature/cursor-pagination-task-instances-ui branch April 20, 2026 14:15
@pierrejeambrunpierrejeambrun added this to the Airflow 3.2.2 milestone Apr 20, 2026
pierrejeambrun added a commit to astronomer/airflow that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
pierrejeambrun added a commit that referenced this pull request Apr 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 23, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request Apr 27, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
vatsrahul1001 pushed a commit that referenced this pull request May 20, 2026
* UI: Switch TaskInstances table to cursor-based pagination
Replace offset-based pagination with cursor-based pagination
for the TaskInstances listing page, leveraging the new cursor
API endpoint. Pagination now shows only previous/next buttons
without page numbers or total count, which eliminates the
expensive COUNT(*) query for large datasets.
Add generic cursor pagination support to DataTable via an
optional cursorPagination prop so other tables can adopt it.
* Small adjustments and cleaning
* Address review: cursor in TableState, no useCallback/useEffect
* Reuse Pagination.Root for cursor pagination instead of custom buttons
* Small updates
(cherry picked from commit 44ae2bc)
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:airflow-ctlarea:APIAirflow's REST/HTTP APIarea:UIRelated to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pierrejeambrun@bbovenzi