Skip to content

Commit

Permalink
Fixes to List Workflows Basic route handler (#758)
Browse files Browse the repository at this point in the history
Add extra validation to Zod schema to ensure that only one filter is set
Explicitly pass filter type to GRPC endpoint
Rewrite the endpoint logic a bit to fix type errors
  • Loading branch information
adhityamamallan authored Dec 13, 2024
1 parent 3245b9a commit 8943728
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 40 deletions.
50 changes: 30 additions & 20 deletions src/route-handlers/list-workflows-basic/list-workflows-basic.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type NextRequest, NextResponse } from 'next/server';

import { type ListOpenWorkflowExecutionsRequest__Input } from '@/__generated__/proto-ts/uber/cadence/api/v1/ListOpenWorkflowExecutionsRequest';
import decodeUrlParams from '@/utils/decode-url-params';
import { getHTTPStatusCode, GRPCError } from '@/utils/grpc/grpc-error';
import logger, { type RouteHandlerErrorPayload } from '@/utils/logger';
Expand Down Expand Up @@ -38,33 +39,42 @@ export async function listWorkflowsBasic(
);
}

try {
const listEndpoint =
queryParams.kind === 'open'
? ctx.grpcClusterMethods.openWorkflows
: ctx.grpcClusterMethods.closedWorkflows;

const res = await listEndpoint({
domain: decodedParams.domain,
pageSize: queryParams.pageSize,
nextPageToken: queryParams.nextPage,
startTimeFilter: {
earliestTime: queryParams.timeRangeStart,
latestTime: queryParams.timeRangeEnd,
},
const baseParams = {
domain: decodedParams.domain,
pageSize: queryParams.pageSize,
nextPageToken: queryParams.nextPage,
startTimeFilter: {
earliestTime: queryParams.timeRangeStart,
latestTime: queryParams.timeRangeEnd,
},
...((queryParams.workflowId || queryParams.runId) && {
filters: 'executionFilter',
executionFilter: {
workflowId: queryParams.workflowId,
runId: queryParams.runId,
},
}),
...(queryParams.workflowType && {
filters: 'typeFilter',
typeFilter: {
name: queryParams.workflowType,
},
...(queryParams.kind === 'closed' && {
statusFilter: {
status: queryParams.closeStatus,
},
}),
});
}),
} satisfies ListOpenWorkflowExecutionsRequest__Input;

try {
const res =
queryParams.kind === 'closed'
? await ctx.grpcClusterMethods.closedWorkflows({
...baseParams,
...(queryParams.closeStatus && {
filters: 'statusFilter',
statusFilter: {
status: queryParams.closeStatus,
},
}),
})
: await ctx.grpcClusterMethods.openWorkflows({ ...baseParams });

const response: ListWorkflowsBasicResponse = {
workflows: mapExecutionsToWorkflows(res.executions),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,44 @@ import getGrpcTimestampFromIso from '@/utils/datetime/get-grpc-timestamp-from-is
import isWorkflowStatus from '@/views/shared/workflow-status-tag/helpers/is-workflow-status';
import { type WorkflowStatus } from '@/views/shared/workflow-status-tag/workflow-status-tag.types';

const listWorkflowsBasicQueryParamsSchema = z.object({
kind: z.enum(['open', 'closed']),
pageSize: z
.string()
.transform((val) => parseInt(val, 10))
.pipe(
z.number().positive({ message: 'Page size must be a positive integer' })
),
workflowId: z.string().optional(),
workflowType: z.string().optional(),
runId: z.string().optional(),
closeStatus: z
.custom<WorkflowStatus>(isWorkflowStatus, {
message: 'Invalid workflow status',
})
.optional(),
timeRangeStart: z.string().datetime().transform(getGrpcTimestampFromIso),
timeRangeEnd: z.string().datetime().transform(getGrpcTimestampFromIso),
nextPage: z.string().optional(),
});
const listWorkflowsBasicQueryParamsSchema = z
.object({
kind: z.enum(['open', 'closed']),
pageSize: z
.string()
.transform((val) => parseInt(val, 10))
.pipe(
z.number().positive({ message: 'Page size must be a positive integer' })
),
workflowId: z.string().optional(),
workflowType: z.string().optional(),
runId: z.string().optional(),
closeStatus: z
.custom<WorkflowStatus>(isWorkflowStatus, {
message: 'Invalid workflow status',
})
.optional(),
timeRangeStart: z.string().datetime().transform(getGrpcTimestampFromIso),
timeRangeEnd: z.string().datetime().transform(getGrpcTimestampFromIso),
nextPage: z.string().optional(),
})
.refine((params) => {
let definedFiltersCount = 0;
// Execution filter
if (params.workflowId || params.runId) {
definedFiltersCount += 1;
}
// Type filter
if (params.workflowType) {
definedFiltersCount += 1;
}
// Status filter
if (params.closeStatus) {
definedFiltersCount += 1;
}

return definedFiltersCount <= 1;
// TODO @adhitya.mamallan - If we add RunID back, add it in the message below
}, 'Only one of the following filters is allowed - Workflow ID, Workflow Type, Close Status');

export default listWorkflowsBasicQueryParamsSchema;

0 comments on commit 8943728

Please sign in to comment.