Skip to content

Commit

Permalink
[UI v2] feat: Adds api hooks for work queues and updates routing
Browse files Browse the repository at this point in the history
  • Loading branch information
devinvillarosa committed Jan 20, 2025
1 parent 6b560c8 commit 6d506ca
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 28 deletions.
5 changes: 5 additions & 0 deletions ui-v2/src/api/work-queues/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export {
type WorkQueue,
type WorkQueuesFilter,
buildFilterWorkQueuesQuery,
} from "./work-queues";
33 changes: 33 additions & 0 deletions ui-v2/src/api/work-queues/work-queues.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { createFakeWorkQueue } from "@/mocks";
import { QueryClient, useSuspenseQuery } from "@tanstack/react-query";
import { renderHook, waitFor } from "@testing-library/react";
import { buildApiUrl, createWrapper, server } from "@tests/utils";
import { http, HttpResponse } from "msw";
import { describe, expect, it } from "vitest";
import { type WorkQueue, buildFilterWorkQueuesQuery } from "./work-queues";

describe("work queues api", () => {
const mockFetchWorkQueuesAPI = (workPools: Array<WorkQueue>) => {
server.use(
http.post(buildApiUrl("/work_queues/filter"), () => {
return HttpResponse.json(workPools);
}),
);
};

describe("buildFilterWorkPoolsQuery", () => {
it("fetches filtered workpools", async () => {
const workQueue = createFakeWorkQueue();
mockFetchWorkQueuesAPI([workQueue]);

const queryClient = new QueryClient();
const { result } = renderHook(
() => useSuspenseQuery(buildFilterWorkQueuesQuery()),
{ wrapper: createWrapper({ queryClient }) },
);

await waitFor(() => expect(result.current.isSuccess).toBe(true));
expect(result.current.data).toEqual([workQueue]);
});
});
});
65 changes: 65 additions & 0 deletions ui-v2/src/api/work-queues/work-queues.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { components } from "@/api/prefect";
import { getQueryService } from "@/api/service";
import { queryOptions } from "@tanstack/react-query";

export type WorkQueue = components["schemas"]["WorkQueue"];
export type WorkQueuesFilter =
components["schemas"]["Body_read_work_queues_work_queues_filter_post"];

/**
* Query key factory for work queues-related queries
*
* @property {function} all - Returns base key for all work queue queries
* @property {function} lists - Returns key for all list-type work queue queries
* @property {function} list - Generates key for specific filtered work queue queries
*
* ```
* all => ['work-queues']
* lists => ['work-queues', 'list']
* list => ['work-queues', 'list', { ...filter }]
* ```
*/
export const queryKeyFactory = {
all: () => ["work-queues"] as const,
lists: () => [...queryKeyFactory.all(), "list"] as const,
list: (filter: WorkQueuesFilter) =>
[...queryKeyFactory.lists(), filter] as const,
};

// ----------------------------
// Query Options Factories
// ----------------------------

/**
* Builds a query configuration for fetching filtered work queues
*
* @param filter - Filter options including:
* - limit: Number of items per page (default: 10)
* - offset: Offset of results based on the limit
* - work_queues: Optional work queues-specific filters
* @returns Query configuration object for use with TanStack Query
*
* @example
* ```ts
* const query = useQuery(buildFilterWorkQueuesQuery({
* limit: 100,
* offset: 0
* }));
* ```
*/
export const buildFilterWorkQueuesQuery = (
filter: WorkQueuesFilter = { offset: 0 },
) =>
queryOptions({
queryKey: queryKeyFactory.list(filter),
queryFn: async () => {
const res = await getQueryService().POST("/work_queues/filter", {
body: filter,
});
if (!res.data) {
throw new Error("'data' expected");
}
return res.data;
},
});
20 changes: 20 additions & 0 deletions ui-v2/src/mocks/create-fake-work-queue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { components } from "@/api/prefect";
import { faker } from "@faker-js/faker";

export const createFakeWorkQueue = (
overrides?: Partial<components["schemas"]["WorkQueue"]>,
): components["schemas"]["WorkQueue"] => {
return {
created: faker.date.past().toISOString(),
description: `${faker.word.adjective()} ${faker.word.noun()}`,
id: faker.string.uuid(),
name: `${faker.word.adjective()} work queue`,
updated: faker.date.past().toISOString(),
concurrency_limit: faker.number.int({ min: 0, max: 1_000 }),
is_paused: faker.datatype.boolean(),
last_polled: faker.date.past().toISOString(),
work_pool_id: `${faker.word.adjective()} work pool`,
priority: faker.number.int({ min: 1, max: 5 }),
...overrides,
};
};
1 change: 1 addition & 0 deletions ui-v2/src/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export { createFakeSchedule } from "./create-fake-schedule";
export { createFakeState } from "./create-fake-state";
export { createFakeTaskRunConcurrencyLimit } from "./create-fake-take-run-concurrency-limit";
export { createFakeTaskRun } from "./create-fake-task-run";
export { createFakeWorkQueue } from "./create-fake-work-queue";
Loading

0 comments on commit 6d506ca

Please sign in to comment.