This is an automated email from the ASF dual-hosted git repository.

rahulvats pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-1-test by this push:
     new c4290ab3a83 [v3-1-test] Return empty list for queued asset events 
instead of 404 (#62934) (#62976)
c4290ab3a83 is described below

commit c4290ab3a83204d720934111a55c3e61e0422584
Author: Wei Lee <[email protected]>
AuthorDate: Fri Mar 6 14:50:42 2026 +0800

    [v3-1-test] Return empty list for queued asset events instead of 404 
(#62934) (#62976)
    
    * [v3-1-test] Return empty list for queued asset events instead of 404 
(#62934)
    (cherry picked from commit f08f5975e7d93844ff8f226fb32ed27b243255fa)
    
    Co-authored-by: Guan-Ming (Wesley) Chiu 
<[email protected]>
    
    * fixup! [v3-1-test] Return empty list for queued asset events instead of 
404 (#62934) (cherry picked from commit 
f08f5975e7d93844ff8f226fb32ed27b243255fa)
    
    * fixup! fixup! [v3-1-test] Return empty list for queued asset events 
instead of 404 (#62934) (cherry picked from commit 
f08f5975e7d93844ff8f226fb32ed27b243255fa)
    
    ---------
    
    Co-authored-by: Guan-Ming (Wesley) Chiu 
<[email protected]>
---
 .../core_api/openapi/v2-rest-api-generated.yaml    | 12 -------
 .../api_fastapi/core_api/routes/public/assets.py   | 10 ------
 .../config_templates/airflow_local_settings.py     |  4 +--
 .../ui/openapi-gen/requests/services.gen.ts        |  2 --
 .../airflow/ui/openapi-gen/requests/types.gen.ts   |  8 -----
 .../src/airflow/ui/src/pages/Dag/Header.tsx        |  1 -
 .../ui/src/pages/DagsList/AssetSchedule.tsx        | 39 ++++++----------------
 .../src/airflow/ui/src/pages/DagsList/DagCard.tsx  |  1 -
 .../src/airflow/ui/src/pages/DagsList/DagsList.tsx | 21 +++++-------
 .../src/airflow/ui/src/pages/DagsList/Schedule.tsx | 16 ++-------
 .../core_api/routes/public/test_assets.py          | 12 +++----
 11 files changed, 29 insertions(+), 97 deletions(-)

diff --git 
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
 
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
index 0f4fa84182c..7e8afefeb71 100644
--- 
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
+++ 
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
@@ -545,12 +545,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/HTTPExceptionResponse'
           description: Forbidden
-        '404':
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/HTTPExceptionResponse'
-          description: Not Found
         '422':
           description: Validation Error
           content:
@@ -700,12 +694,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/HTTPExceptionResponse'
           description: Forbidden
-        '404':
-          content:
-            application/json:
-              schema:
-                $ref: '#/components/schemas/HTTPExceptionResponse'
-          description: Not Found
         '422':
           description: Validation Error
           content:
diff --git 
a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/assets.py 
b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/assets.py
index a00739564f8..b1bafae7766 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/assets.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/assets.py
@@ -390,7 +390,6 @@ def materialize_asset(
 
 @assets_router.get(
     "/assets/{asset_id}/queuedEvents",
-    responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]),
     dependencies=[Depends(requires_access_asset(method="GET"))],
 )
 def get_asset_queued_events(
@@ -408,12 +407,6 @@ def get_asset_queued_events(
     dag_asset_queued_events_select, total_entries = 
paginated_select(statement=query)
     adrqs = session.scalars(dag_asset_queued_events_select).all()
 
-    if not adrqs:
-        raise HTTPException(
-            status.HTTP_404_NOT_FOUND,
-            f"Queue event with asset_id: `{asset_id}` was not found",
-        )
-
     queued_events = [
         QueuedEventResponse(
             created_at=adrq.created_at,
@@ -486,7 +479,6 @@ def get_asset(
 
 @assets_router.get(
     "/dags/{dag_id}/assets/queuedEvents",
-    responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]),
     dependencies=[Depends(requires_access_asset(method="GET")), 
Depends(requires_access_dag(method="GET"))],
 )
 def get_dag_asset_queued_events(
@@ -503,8 +495,6 @@ def get_dag_asset_queued_events(
 
     dag_asset_queued_events_select, total_entries = 
paginated_select(statement=query)
     adrqs = session.scalars(dag_asset_queued_events_select).all()
-    if not adrqs:
-        raise HTTPException(status.HTTP_404_NOT_FOUND, f"Queue event with 
dag_id: `{dag_id}` was not found")
 
     queued_events = [
         QueuedEventResponse(
diff --git 
a/airflow-core/src/airflow/config_templates/airflow_local_settings.py 
b/airflow-core/src/airflow/config_templates/airflow_local_settings.py
index 3a547aa58ee..51331d209ec 100644
--- a/airflow-core/src/airflow/config_templates/airflow_local_settings.py
+++ b/airflow-core/src/airflow/config_templates/airflow_local_settings.py
@@ -282,8 +282,8 @@ if REMOTE_LOGGING:
         )
         remote_task_handler_kwargs = {}
     elif ELASTICSEARCH_HOST:
-        from airflow.providers.elasticsearch.log.es_task_handler import (
-            ElasticsearchRemoteLogIO,  # type: ignore[attr-defined]
+        from airflow.providers.elasticsearch.log.es_task_handler import (  # 
type: ignore[attr-defined]
+            ElasticsearchRemoteLogIO,
         )
 
         ELASTICSEARCH_WRITE_STDOUT: bool = conf.getboolean("elasticsearch", 
"WRITE_STDOUT")
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts 
b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
index 153da21a141..645e62d5fa2 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -212,7 +212,6 @@ export class AssetService {
             errors: {
                 401: 'Unauthorized',
                 403: 'Forbidden',
-                404: 'Not Found',
                 422: 'Validation Error'
             }
         });
@@ -292,7 +291,6 @@ export class AssetService {
             errors: {
                 401: 'Unauthorized',
                 403: 'Forbidden',
-                404: 'Not Found',
                 422: 'Validation Error'
             }
         });
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts 
b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
index 29e7b3f6031..efb5de0f958 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -3493,10 +3493,6 @@ export type $OpenApiTs = {
                  * Forbidden
                  */
                 403: HTTPExceptionResponse;
-                /**
-                 * Not Found
-                 */
-                404: HTTPExceptionResponse;
                 /**
                  * Validation Error
                  */
@@ -3572,10 +3568,6 @@ export type $OpenApiTs = {
                  * Forbidden
                  */
                 403: HTTPExceptionResponse;
-                /**
-                 * Not Found
-                 */
-                404: HTTPExceptionResponse;
                 /**
                  * Validation Error
                  */
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx
index 84913f45fd7..bee669e6943 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Header.tsx
@@ -67,7 +67,6 @@ export const Header = ({
           <Schedule
             assetExpression={dag.asset_expression}
             dagId={dag.dag_id}
-            latestRunAfter={latestRunInfo?.run_after}
             timetableDescription={dag.timetable_description}
             timetableSummary={dag.timetable_summary}
           />
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/AssetSchedule.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/AssetSchedule.tsx
index fe1962e891a..7118d601172 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/AssetSchedule.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/AssetSchedule.tsx
@@ -31,48 +31,31 @@ import { Button, Popover } from "src/components/ui";
 type Props = {
   readonly assetExpression?: ExpressionType | null;
   readonly dagId: string;
-  readonly latestRunAfter?: string;
   readonly timetableSummary: string | null;
 };
 
-export const AssetSchedule = ({ assetExpression, dagId, latestRunAfter, 
timetableSummary }: Props) => {
+export const AssetSchedule = ({ assetExpression, dagId, timetableSummary }: 
Props) => {
   const { t: translate } = useTranslation(["dags", "common"]);
 
   const { data: nextRun, isLoading: isNextRunLoading } = 
useAssetServiceNextRunAssets({ dagId });
-  const {
-    data: queuedEventsData,
-    error: queuedEventsError,
-    isLoading: isQueuedEventsLoading,
-  } = useAssetServiceGetDagAssetQueuedEvents({ dagId }, undefined);
+  const { data: queuedEventsData, isLoading: isQueuedEventsLoading } = 
useAssetServiceGetDagAssetQueuedEvents(
+    { dagId },
+    undefined,
+    { enabled: true },
+  );
 
   const nextRunEvents = (nextRun?.events ?? []) as Array<NextRunEvent>;
-  const queuedEventsErrorStatus =
-    typeof queuedEventsError === "object" && queuedEventsError !== null && 
"status" in queuedEventsError
-      ? (queuedEventsError as { status?: number }).status
-      : undefined;
-  const hasQueuedEventsError = Boolean(queuedEventsError) && 
queuedEventsErrorStatus !== 404;
   const queuedAssetEvents = new Map<number, string>();
 
-  if (!hasQueuedEventsError) {
-    for (const event of queuedEventsData?.queued_events ?? []) {
-      // Keep a single event timestamp per asset, using the latest one when 
duplicates exist.
-      const existingEventDate = queuedAssetEvents.get(event.asset_id);
+  for (const event of queuedEventsData?.queued_events ?? []) {
+    // Keep a single event timestamp per asset, using the latest one when 
duplicates exist.
+    const existingEventDate = queuedAssetEvents.get(event.asset_id);
 
-      if (existingEventDate === undefined || 
dayjs(event.created_at).isAfter(existingEventDate)) {
-        queuedAssetEvents.set(event.asset_id, event.created_at);
-      }
+    if (existingEventDate === undefined || 
dayjs(event.created_at).isAfter(existingEventDate)) {
+      queuedAssetEvents.set(event.asset_id, event.created_at);
     }
   }
-
   const pendingEvents = nextRunEvents.flatMap((event) => {
-    if (hasQueuedEventsError) {
-      if (event.lastUpdate === null) {
-        return [];
-      }
-
-      return latestRunAfter !== undefined && 
dayjs(event.lastUpdate).isAfter(latestRunAfter) ? [event] : [];
-    }
-
     const queuedAt = queuedAssetEvents.get(event.id);
 
     return queuedAt === undefined ? [] : [{ ...event, lastUpdate: 
event.lastUpdate ?? queuedAt }];
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagCard.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagCard.tsx
index a43233feb9b..de2487175d3 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagCard.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagCard.tsx
@@ -81,7 +81,6 @@ export const DagCard = ({ dag }: Props) => {
           <Schedule
             assetExpression={dag.asset_expression}
             dagId={dag.dag_id}
-            latestRunAfter={latestRun?.run_after}
             timetableDescription={dag.timetable_description}
             timetableSummary={dag.timetable_summary}
           />
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
index 0c32a2568e8..b3f62bfd9d2 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
@@ -86,19 +86,14 @@ const createColumns = (
   },
   {
     accessorKey: "timetable_description",
-    cell: ({ row: { original } }) => {
-      const [latestRun] = original.latest_dag_runs;
-
-      return (
-        <Schedule
-          assetExpression={original.asset_expression}
-          dagId={original.dag_id}
-          latestRunAfter={latestRun?.run_after}
-          timetableDescription={original.timetable_description}
-          timetableSummary={original.timetable_summary}
-        />
-      );
-    },
+    cell: ({ row: { original } }) => (
+      <Schedule
+        assetExpression={original.asset_expression}
+        dagId={original.dag_id}
+        timetableDescription={original.timetable_description}
+        timetableSummary={original.timetable_summary}
+      />
+    ),
     enableSorting: false,
     header: () => translate("dagDetails.schedule"),
   },
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/Schedule.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/Schedule.tsx
index ca8f39215c2..c02eac648a7 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/Schedule.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/Schedule.tsx
@@ -28,28 +28,16 @@ import { AssetSchedule } from "./AssetSchedule";
 type Props = {
   readonly assetExpression: ExpressionType | null | undefined;
   readonly dagId: string;
-  readonly latestRunAfter?: string;
   readonly timetableDescription?: string | null;
   readonly timetableSummary: string | null;
 };
 
-export const Schedule = ({
-  assetExpression,
-  dagId,
-  latestRunAfter,
-  timetableDescription,
-  timetableSummary,
-}: Props) => {
+export const Schedule = ({ assetExpression, dagId, timetableDescription, 
timetableSummary }: Props) => {
   const { t: translate } = useTranslation("dags");
 
   return Boolean(timetableSummary) ? (
     Boolean(assetExpression) || timetableSummary === 
translate("schedule.asset") ? (
-      <AssetSchedule
-        assetExpression={assetExpression}
-        dagId={dagId}
-        latestRunAfter={latestRunAfter}
-        timetableSummary={timetableSummary}
-      />
+      <AssetSchedule assetExpression={assetExpression} dagId={dagId} 
timetableSummary={timetableSummary} />
     ) : (
       <Tooltip content={timetableDescription}>
         <Text fontSize="sm">
diff --git 
a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_assets.py 
b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_assets.py
index ddb7d8e7a94..625b5abc9d7 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_assets.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_assets.py
@@ -1035,15 +1035,15 @@ class 
TestGetDagAssetQueuedEvents(TestQueuedEventEndpoint):
         response = 
unauthorized_test_client.get("/dags/random/assets/queuedEvents")
         assert response.status_code == 403
 
-    def test_should_respond_404(self, test_client):
+    def test_should_respond_200_empty(self, test_client):
         dag_id = "not_exists"
 
         response = test_client.get(
             f"/dags/{dag_id}/assets/queuedEvents",
         )
 
-        assert response.status_code == 404
-        assert response.json()["detail"] == "Queue event with dag_id: 
`not_exists` was not found"
+        assert response.status_code == 200
+        assert response.json() == {"queued_events": [], "total_entries": 0}
 
 
 class TestDeleteDagDatasetQueuedEvents(TestQueuedEventEndpoint):
@@ -1294,10 +1294,10 @@ class TestGetAssetQueuedEvents(TestQueuedEventEndpoint):
         response = unauthorized_test_client.get("/assets/1/queuedEvents")
         assert response.status_code == 403
 
-    def test_should_respond_404(self, test_client):
+    def test_should_respond_200_empty(self, test_client):
         response = test_client.get("/assets/1/queuedEvents")
-        assert response.status_code == 404
-        assert response.json()["detail"] == "Queue event with asset_id: `1` 
was not found"
+        assert response.status_code == 200
+        assert response.json() == {"queued_events": [], "total_entries": 0}
 
 
 class TestDeleteAssetQueuedEvents(TestQueuedEventEndpoint):

Reply via email to