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

jscheffl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 4990e07b95a Add Filtering to Edge UI Plugin Jobs Page (#61934)
4990e07b95a is described below

commit 4990e07b95a1087b9d2718e89ccea108b259ece0
Author: Eason09053360 <[email protected]>
AuthorDate: Thu Feb 19 05:14:58 2026 +0800

    Add Filtering to Edge UI Plugin Jobs Page (#61934)
    
    * Add Filtering to Edge UI Plugin Jobs Page
    
    * Add filtering to Edge UI Plugin Jobs Page but not Regenerate OpenAPI 
client for Edge3 plugin
    
    * Includes archives automatically generated by openapi-gen
    
    * Fix JobsPage.tsx syntax error after rebase
    
    - Resolving conflict issues
    
    * fix: Correct API client usage and add job filtering parameters
    
    - Back to the old version of codegen
    
    * - Add runIdPattern state and search bar
    
    * Add clickable filters from Worker to Jobs page in Edge UI
    
    This commit implements navigation links between the Worker and Jobs pages:
    
    1. **WorkerPage.tsx changes**:
       - Queue names now link to Jobs page filtered by queue
       - Active job counts (when > 0) link to Jobs page filtered by worker name
       - Added URL parameter encoding for safe navigation
    
    2. **JobsPage.tsx changes**:
       - Added URL parameter support (queue, worker) to pre-filter jobs
       - Added useEffect to sync URL parameters with search state
       - Added key props to SearchBar components to force re-render on state 
changes
       - Improved empty state messaging: now distinguishes between "no jobs" vs 
"no matches for current filters"
    
    3. **package.json change**:
       - Fixed codegen command to use 'axios' instead of '@hey-api/client-axios'
    
    The "no match" message enhancement:
    When users click a queue or worker link from the Worker page, if there are
    no matching jobs, they will see "No jobs match the current filters. Try
    adjusting or clearing filters." instead of the generic "Currently no jobs
    running" message.
    
    ---------
    
    Co-authored-by: Eason09053360 <[email protected]>
---
 .../plugins/www/openapi-gen/queries/common.ts      |   9 +-
 .../plugins/www/openapi-gen/queries/queries.ts     |   9 +-
 .../www/openapi-gen/requests/services.gen.ts       |  19 +-
 .../providers/edge3/plugins/www/package.json       |   2 +-
 .../providers/edge3/plugins/www/src/constants.ts   |  17 +-
 .../edge3/plugins/www/src/pages/JobsPage.tsx       | 204 ++++++++++++++++++---
 .../edge3/plugins/www/src/pages/WorkerPage.tsx     |  21 ++-
 .../providers/edge3/worker_api/routes/ui.py        |  21 ++-
 .../edge3/worker_api/v2-edge-generated.yaml        |  63 ++++++-
 9 files changed, 319 insertions(+), 46 deletions(-)

diff --git 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/queries/common.ts
 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/queries/common.ts
index 3daeddc5d75..4d553521aea 100644
--- 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/queries/common.ts
+++ 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/queries/common.ts
@@ -29,7 +29,14 @@ export const UseUiServiceWorkerKeyFn = ({ queueNamePattern, 
state, workerNamePat
 export type UiServiceJobsDefaultResponse = Awaited<ReturnType<typeof 
UiService.jobs>>;
 export type UiServiceJobsQueryResult<TData = UiServiceJobsDefaultResponse, 
TError = unknown> = UseQueryResult<TData, TError>;
 export const useUiServiceJobsKey = "UiServiceJobs";
-export const UseUiServiceJobsKeyFn = (queryKey?: Array<unknown>) => 
[useUiServiceJobsKey, ...(queryKey ?? [])];
+export const UseUiServiceJobsKeyFn = ({ dagIdPattern, runIdPattern, 
taskIdPattern, state, queuePattern, workerNamePattern }: {
+  dagIdPattern?: string;
+  runIdPattern?: string;
+  taskIdPattern?: string;
+  state?: TaskInstanceState[];
+  queuePattern?: string;
+  workerNamePattern?: string;
+} = {}, queryKey?: Array<unknown>) => [useUiServiceJobsKey, ...(queryKey ?? [{ 
dagIdPattern, runIdPattern, taskIdPattern, state, queuePattern, 
workerNamePattern }])];
 export type JobsServiceFetchMutationResult = Awaited<ReturnType<typeof 
JobsService.fetch>>;
 export type LogsServicePushLogsMutationResult = Awaited<ReturnType<typeof 
LogsService.pushLogs>>;
 export type WorkerServiceRegisterMutationResult = Awaited<ReturnType<typeof 
WorkerService.register>>;
diff --git 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/queries/queries.ts
 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/queries/queries.ts
index 2948bf0eb53..782a26bbf91 100644
--- 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/queries/queries.ts
+++ 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/queries/queries.ts
@@ -18,7 +18,14 @@ export const useUiServiceWorker = <TData = 
Common.UiServiceWorkerDefaultResponse
   state?: EdgeWorkerState[];
   workerNamePattern?: string;
 } = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, 
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: 
Common.UseUiServiceWorkerKeyFn({ queueNamePattern, state, workerNamePattern }, 
queryKey), queryFn: () => UiService.worker({ queueNamePattern, state, 
workerNamePattern }) as TData, ...options });
-export const useUiServiceJobs = <TData = Common.UiServiceJobsDefaultResponse, 
TError = unknown, TQueryKey extends Array<unknown> = unknown[]>(queryKey?: 
TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | 
"queryFn">) => useQuery<TData, TError>({ queryKey: 
Common.UseUiServiceJobsKeyFn(queryKey), queryFn: () => UiService.jobs() as 
TData, ...options });
+export const useUiServiceJobs = <TData = Common.UiServiceJobsDefaultResponse, 
TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ dagIdPattern, 
runIdPattern, taskIdPattern, state, queuePattern, workerNamePattern }: {
+  dagIdPattern?: string;
+  runIdPattern?: string;
+  taskIdPattern?: string;
+  state?: TaskInstanceState[];
+  queuePattern?: string;
+  workerNamePattern?: string;
+} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, 
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: 
Common.UseUiServiceJobsKeyFn({ dagIdPattern, runIdPattern, taskIdPattern, 
state, queuePattern, workerNamePattern }, queryKey), queryFn: () => 
UiService.jobs({ dagIdPattern, runIdPattern, taskIdPattern, state, 
queuePattern, workerNamePattern }) as TData, ...options });
 export const useJobsServiceFetch = <TData = 
Common.JobsServiceFetchMutationResult, TError = unknown, TContext = 
unknown>(options?: Omit<UseMutationOptions<TData, TError, {
   authorization: string;
   requestBody: WorkerQueuesBody;
diff --git 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/requests/services.gen.ts
 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/requests/services.gen.ts
index e8decd8af76..da00585e044 100644
--- 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/requests/services.gen.ts
+++ 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/openapi-gen/requests/services.gen.ts
@@ -291,13 +291,28 @@ export class UiService {
     /**
      * Jobs
      * Return Edge Jobs.
+     * @param data The data for the request.
+     * @param data.dagIdPattern
+     * @param data.runIdPattern
+     * @param data.taskIdPattern
+     * @param data.state
+     * @param data.queuePattern
+     * @param data.workerNamePattern
      * @returns JobCollectionResponse Successful Response
      * @throws ApiError
      */
-    public static jobs(): CancelablePromise<JobsResponse> {
+    public static jobs(data: { dagIdPattern?: string; runIdPattern?: string; 
taskIdPattern?: string; state?: TaskInstanceState[]; queuePattern?: string; 
workerNamePattern?: string } = {}): CancelablePromise<JobsResponse> {
         return __request(OpenAPI, {
             method: 'GET',
-            url: '/edge_worker/ui/jobs'
+            url: '/edge_worker/ui/jobs',
+            query: {
+                dag_id_pattern: data.dagIdPattern,
+                run_id_pattern: data.runIdPattern,
+                task_id_pattern: data.taskIdPattern,
+                state: data.state,
+                queue_pattern: data.queuePattern,
+                worker_name_pattern: data.workerNamePattern
+            }
         });
     }
     
diff --git 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/package.json 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/package.json
index 2c5acbaee9c..a0b8236ddf9 100644
--- a/providers/edge3/src/airflow/providers/edge3/plugins/www/package.json
+++ b/providers/edge3/src/airflow/providers/edge3/plugins/www/package.json
@@ -27,7 +27,7 @@
     "lint:fix": "eslint --fix && tsc --p tsconfig.app.json",
     "format": "pnpm prettier --write .",
     "preview": "vite preview",
-    "codegen": "openapi-rq -i ../../worker_api/v2-edge-generated.yaml -c axios 
--format prettier -o openapi-gen --operationId",
+    "codegen": "openapi-rq -i ../../worker_api/v2-edge-generated.yaml -c axios 
--format prettier -o openapi-gen",
     "test": "vitest run",
     "coverage": "vitest run --coverage"
   },
diff --git 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/constants.ts 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/constants.ts
index bdb9d0052d4..6e82544f7be 100644
--- a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/constants.ts
+++ b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/constants.ts
@@ -18,8 +18,8 @@
  */
 
 import { createListCollection } from "@chakra-ui/react";
-import type { EdgeWorkerState } from "../openapi-gen/requests/types.gen";
-import { $EdgeWorkerState } from "../openapi-gen/requests/schemas.gen";
+import type { EdgeWorkerState, TaskInstanceState } from 
"../openapi-gen/requests/types.gen";
+import { $EdgeWorkerState, $TaskInstanceState } from 
"../openapi-gen/requests/schemas.gen";
 
 // Helper function to convert snake_case or space-separated strings to Title 
Case
 const toTitleCase = (str: string): string => {
@@ -41,3 +41,16 @@ export const workerStateOptions = createListCollection<{
     })),
   ],
 });
+
+export const jobStateOptions = createListCollection<{
+  label: string;
+  value: TaskInstanceState | "all";
+}>({
+  items: [
+    { label: "All States", value: "all" },
+    ...$TaskInstanceState.enum.map((state) => ({
+      label: toTitleCase(state),
+      value: state as TaskInstanceState,
+    })),
+  ],
+});
diff --git 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/JobsPage.tsx
 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/JobsPage.tsx
index 72e023eee75..a2ce7213a3e 100644
--- 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/JobsPage.tsx
+++ 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/JobsPage.tsx
@@ -16,24 +16,179 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Table, Text } from "@chakra-ui/react";
+import { Box, HStack, Table, Text, type SelectValueChangeDetails } from 
"@chakra-ui/react";
+import { useState, useCallback, useEffect } from "react";
 import { useUiServiceJobs } from "openapi/queries";
-import { Link } from "react-router-dom";
+import { Link, useSearchParams } from "react-router-dom";
 import TimeAgo from "react-timeago";
 
 import { ErrorAlert } from "src/components/ErrorAlert";
+import { SearchBar } from "src/components/SearchBar";
 import { StateBadge } from "src/components/StateBadge";
+import { Select } from "src/components/ui";
+import { jobStateOptions } from "src/constants";
 import { autoRefreshInterval } from "src/utils";
+import type { TaskInstanceState } from "openapi/requests/types.gen";
 
 export const JobsPage = () => {
-  const { data, error } = useUiServiceJobs(undefined, {
-    enabled: true,
-    refetchInterval: autoRefreshInterval,
-  });
+  const [searchParams] = useSearchParams();
+  const [dagIdPattern, setDagIdPattern] = useState(searchParams.get("dagId") 
|| "");
+  const [runIdPattern, setRunIdPattern] = useState(searchParams.get("runId") 
|| "");
+  const [taskIdPattern, setTaskIdPattern] = 
useState(searchParams.get("taskId") || "");
+  const [queuePattern, setQueuePattern] = useState(searchParams.get("queue") 
|| "");
+  const [workerNamePattern, setWorkerNamePattern] = 
useState(searchParams.get("worker") || "");
+  const [filteredState, setFilteredState] = useState<string[]>([]);
 
-  if (data?.jobs && data.jobs.length > 0)
-    return (
-      <Box p={2}>
+  useEffect(() => {
+    const queueFromUrl = searchParams.get("queue");
+    const workerFromUrl = searchParams.get("worker");
+    setQueuePattern(queueFromUrl || "");
+    setWorkerNamePattern(workerFromUrl || "");
+  }, [searchParams]);
+
+  const hasFilteredState = filteredState.length > 0;
+  const hasFilters =
+    hasFilteredState ||
+    Boolean(dagIdPattern || runIdPattern || taskIdPattern || queuePattern || 
workerNamePattern);
+
+  const { data, error } = useUiServiceJobs(
+    {
+      dagIdPattern: dagIdPattern || undefined,
+      runIdPattern: runIdPattern || undefined,
+      taskIdPattern: taskIdPattern || undefined,
+      queuePattern: queuePattern || undefined,
+      workerNamePattern: workerNamePattern || undefined,
+      state: hasFilteredState ? (filteredState as TaskInstanceState[]) : 
undefined,
+    },
+    undefined,
+    {
+      enabled: true,
+      refetchInterval: autoRefreshInterval,
+    },
+  );
+
+  const handleDagIdSearchChange = (value: string) => {
+    setDagIdPattern(value);
+  };
+
+  const handleRunIdSearchChange = (value: string) => {
+    setRunIdPattern(value);
+  };
+
+  const handleTaskIdSearchChange = (value: string) => {
+    setTaskIdPattern(value);
+  };
+
+  const handleQueueSearchChange = (value: string) => {
+    setQueuePattern(value);
+  };
+
+  const handleWorkerSearchChange = (value: string) => {
+    setWorkerNamePattern(value);
+  };
+
+  const handleStateChange = useCallback(({ value }: 
SelectValueChangeDetails<string>) => {
+    const [val, ...rest] = value;
+
+    if ((val === undefined || val === "all") && rest.length === 0) {
+      setFilteredState([]);
+    } else {
+      setFilteredState(value.filter((state) => state !== "all"));
+    }
+  }, []);
+
+  return (
+    <Box p={2}>
+      <HStack gap={4} mb={4}>
+        <SearchBar
+          buttonProps={{ disabled: true }}
+          defaultValue={dagIdPattern}
+          hideAdvanced
+          hotkeyDisabled
+          key={`dag-${dagIdPattern}`}
+          onChange={handleDagIdSearchChange}
+          placeHolder="Search DAG ID"
+        />
+        <SearchBar
+          buttonProps={{ disabled: true }}
+          defaultValue={runIdPattern}
+          hideAdvanced
+          hotkeyDisabled
+          key={`run-${runIdPattern}`}
+          onChange={handleRunIdSearchChange}
+          placeHolder="Search Run ID"
+        />
+        <SearchBar
+          buttonProps={{ disabled: true }}
+          defaultValue={taskIdPattern}
+          hideAdvanced
+          hotkeyDisabled
+          key={`task-${taskIdPattern}`}
+          onChange={handleTaskIdSearchChange}
+          placeHolder="Search Task ID"
+        />
+        <SearchBar
+          buttonProps={{ disabled: true }}
+          defaultValue={queuePattern}
+          hideAdvanced
+          hotkeyDisabled
+          key={`queue-${queuePattern}`}
+          onChange={handleQueueSearchChange}
+          placeHolder="Search Queue"
+        />
+        <SearchBar
+          buttonProps={{ disabled: true }}
+          defaultValue={workerNamePattern}
+          hideAdvanced
+          hotkeyDisabled
+          key={`worker-${workerNamePattern}`}
+          onChange={handleWorkerSearchChange}
+          placeHolder="Search Worker"
+        />
+        <Select.Root
+          collection={jobStateOptions}
+          maxW="450px"
+          multiple
+          onValueChange={handleStateChange}
+          value={hasFilteredState ? filteredState : ["all"]}
+        >
+          <Select.Trigger
+            {...(hasFilteredState ? { clearable: true } : {})}
+            colorPalette="brand"
+            isActive={Boolean(filteredState)}
+          >
+            <Select.ValueText>
+              {() =>
+                hasFilteredState ? (
+                  <HStack flexWrap="wrap" fontSize="sm" gap="4px" 
paddingY="8px">
+                    {filteredState.map((state) => (
+                      <StateBadge key={state} state={state as 
TaskInstanceState}>
+                        {state}
+                      </StateBadge>
+                    ))}
+                  </HStack>
+                ) : (
+                  "All States"
+                )
+              }
+            </Select.ValueText>
+          </Select.Trigger>
+          <Select.Content>
+            {jobStateOptions.items.map((option) => (
+              <Select.Item item={option} key={option.label}>
+                {option.value === "all" ? (
+                  option.label
+                ) : (
+                  <StateBadge state={option.value as 
TaskInstanceState}>{option.label}</StateBadge>
+                )}
+              </Select.Item>
+            ))}
+          </Select.Content>
+        </Select.Root>
+      </HStack>
+      {error ? (
+        <ErrorAlert error={error} />
+      ) : data?.jobs && data.jobs.length > 0 ? (
         <Table.Root size="sm" interactive stickyHeader striped>
           <Table.Header>
             <Table.Row>
@@ -94,26 +249,15 @@ export const JobsPage = () => {
             ))}
           </Table.Body>
         </Table.Root>
-      </Box>
-    );
-  if (data) {
-    return (
-      <Text as="div" pl={4} pt={1}>
-        Currently no jobs running. Start a Dag and then all active jobs should 
show up here. Note that after
-        some (configurable) time, jobs are purged from the list.
-      </Text>
-    );
-  }
-  if (error) {
-    return (
-      <Text as="div" pl={4} pt={1}>
-        <ErrorAlert error={error} />
-      </Text>
-    );
-  }
-  return (
-    <Text as="div" pl={4} pt={1}>
-      Loading...
-    </Text>
+      ) : data ? (
+        <Text>
+          {hasFilters
+            ? "No jobs match the current filters. Try adjusting or clearing 
filters."
+            : "Currently no jobs running. Start a Dag and then all active jobs 
should show up here. Note that after some (configurable) time, jobs are purged 
from the list."}
+        </Text>
+      ) : (
+        <Text>Loading...</Text>
+      )}
+    </Box>
   );
 };
diff --git 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/WorkerPage.tsx
 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/WorkerPage.tsx
index 7340505ff8f..e91edee97e3 100644
--- 
a/providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/WorkerPage.tsx
+++ 
b/providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/WorkerPage.tsx
@@ -16,9 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Code, HStack, Link, List, Table, Text, type 
SelectValueChangeDetails } from "@chakra-ui/react";
+import { Box, Code, HStack, Link as ChakraLink, List, Table, Text, type 
SelectValueChangeDetails } from "@chakra-ui/react";
 import { useState, useCallback } from "react";
 import { useUiServiceWorker } from "openapi/queries";
+import { Link } from "react-router-dom";
 import { LuExternalLink } from "react-icons/lu";
 import TimeAgo from "react-timeago";
 
@@ -161,7 +162,9 @@ export const WorkerPage = () => {
                     {worker.queues ? (
                       <List.Root>
                         {worker.queues.map((queue) => (
-                          <List.Item key={queue}>{queue}</List.Item>
+                          <List.Item key={queue}>
+                            <Link 
to={`../jobs?queue=${encodeURIComponent(queue)}`}>{queue}</Link>
+                          </List.Item>
                         ))}
                       </List.Root>
                     ) : (
@@ -174,7 +177,15 @@ export const WorkerPage = () => {
                   <Table.Cell>
                     {worker.last_heartbeat ? <TimeAgo 
date={worker.last_heartbeat} live={false} /> : undefined}
                   </Table.Cell>
-                  <Table.Cell>{worker.jobs_active}</Table.Cell>
+                  <Table.Cell>
+                    {worker.jobs_active !== undefined && worker.jobs_active > 
0 ? (
+                      <Link 
to={`../jobs?worker=${encodeURIComponent(worker.worker_name)}`}>
+                        {worker.jobs_active}
+                      </Link>
+                    ) : (
+                      worker.jobs_active ?? 0
+                    )}
+                  </Table.Cell>
                   <Table.Cell>
                     {worker.sysinfo ? (
                       <List.Root>
@@ -200,14 +211,14 @@ export const WorkerPage = () => {
       ) : (
         <Text as="div" pl={2} pt={1}>
           No known workers. Start one via <Code>airflow edge worker 
[...]</Code>. See{" "}
-          <Link
+          <ChakraLink
             target="_blank"
             variant="underline"
             color="fg.info"
             
href="https://airflow.apache.org/docs/apache-airflow-providers-edge3/stable/deployment.html";
           >
             Edge Worker Deployment docs <LuExternalLink />
-          </Link>{" "}
+          </ChakraLink>{" "}
           how to deploy a new worker.
         </Text>
       )}
diff --git 
a/providers/edge3/src/airflow/providers/edge3/worker_api/routes/ui.py 
b/providers/edge3/src/airflow/providers/edge3/worker_api/routes/ui.py
index 5339fa4eb28..f24b1e19729 100644
--- a/providers/edge3/src/airflow/providers/edge3/worker_api/routes/ui.py
+++ b/providers/edge3/src/airflow/providers/edge3/worker_api/routes/ui.py
@@ -104,9 +104,28 @@ def worker(
 )
 def jobs(
     session: SessionDep,
+    dag_id_pattern: str | None = None,
+    run_id_pattern: str | None = None,
+    task_id_pattern: str | None = None,
+    state: Annotated[list[TaskInstanceState] | None, Query()] = None,
+    queue_pattern: str | None = None,
+    worker_name_pattern: str | None = None,
 ) -> JobCollectionResponse:
     """Return Edge Jobs."""
-    query = select(EdgeJobModel).order_by(EdgeJobModel.queued_dttm)
+    query = select(EdgeJobModel)
+    if dag_id_pattern:
+        query = query.where(EdgeJobModel.dag_id.ilike(f"%{dag_id_pattern}%"))
+    if run_id_pattern:
+        query = query.where(EdgeJobModel.run_id.ilike(f"%{run_id_pattern}%"))
+    if task_id_pattern:
+        query = query.where(EdgeJobModel.task_id.ilike(f"%{task_id_pattern}%"))
+    if state:
+        query = query.where(EdgeJobModel.state.in_([s.value for s in state]))
+    if queue_pattern:
+        query = query.where(EdgeJobModel.queue.ilike(f"%{queue_pattern}%"))
+    if worker_name_pattern:
+        query = 
query.where(EdgeJobModel.edge_worker.ilike(f"%{worker_name_pattern}%"))
+    query = query.order_by(EdgeJobModel.queued_dttm)
     jobs: ScalarResult[EdgeJobModel] = session.scalars(query)
 
     result = [
diff --git 
a/providers/edge3/src/airflow/providers/edge3/worker_api/v2-edge-generated.yaml 
b/providers/edge3/src/airflow/providers/edge3/worker_api/v2-edge-generated.yaml
index c141442dd2d..293d8700ec7 100644
--- 
a/providers/edge3/src/airflow/providers/edge3/worker_api/v2-edge-generated.yaml
+++ 
b/providers/edge3/src/airflow/providers/edge3/worker_api/v2-edge-generated.yaml
@@ -621,6 +621,60 @@ paths:
       summary: Jobs
       description: Return Edge Jobs.
       operationId: jobs
+      security:
+      - OAuth2PasswordBearer: []
+      - HTTPBearer: []
+      parameters:
+      - name: dag_id_pattern
+        in: query
+        required: false
+        schema:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Dag Id Pattern
+      - name: run_id_pattern
+        in: query
+        required: false
+        schema:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Run Id Pattern
+      - name: task_id_pattern
+        in: query
+        required: false
+        schema:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Task Id Pattern
+      - name: state
+        in: query
+        required: false
+        schema:
+          anyOf:
+          - type: array
+            items:
+              $ref: '#/components/schemas/TaskInstanceState'
+          - type: 'null'
+          title: State
+      - name: queue_pattern
+        in: query
+        required: false
+        schema:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Queue Pattern
+      - name: worker_name_pattern
+        in: query
+        required: false
+        schema:
+          anyOf:
+          - type: string
+          - type: 'null'
+          title: Worker Name Pattern
       responses:
         '200':
           description: Successful Response
@@ -628,9 +682,12 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/JobCollectionResponse'
-      security:
-      - OAuth2PasswordBearer: []
-      - HTTPBearer: []
+        '422':
+          description: Validation Error
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/HTTPValidationError'
   /edge_worker/ui/worker/{worker_name}/maintenance:
     post:
       tags:

Reply via email to