Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🪟🐛 client side validation of cron expressions #17887

Merged
merged 19 commits into from
Oct 19, 2022

Conversation

josephkmh
Copy link
Contributor

@josephkmh josephkmh commented Oct 12, 2022

What

Closes https://github.com/airbytehq/airbyte-cloud/issues/2772

Adds frontend validation of cron expressions

How

I tested various cron parsing libraries, but unfortunately did not find any that work perfectly with the quartz syntax.

Instead of parsing the cron expression, I'm relying on a pretty loose regex for the frontend validation. This will give the user quick feedback if, for example, the cron is too short or has invalid characters. I have included tests for all examples on the quartz docs as well as every single cron expression one of our cloud customers is currently using.

It is possible that an invalid cron expression makes it through the frontend validation. In that case, the backend will return an error which we display to the user.

@github-actions github-actions bot added area/platform issues related to the platform area/frontend Related to the Airbyte webapp labels Oct 12, 2022
@josephkmh josephkmh added team/compose area/frontend Related to the Airbyte webapp ui/connection and removed area/frontend Related to the Airbyte webapp team/compose labels Oct 13, 2022
@josephkmh josephkmh changed the title [DRAFT] 🪟🐛 sync cron expression validation [DRAFT] 🪟🐛 client side validation of cron expressions Oct 13, 2022
@josephkmh josephkmh marked this pull request as ready for review October 13, 2022 13:54
@josephkmh josephkmh requested a review from a team as a code owner October 13, 2022 13:54
@josephkmh josephkmh changed the title [DRAFT] 🪟🐛 client side validation of cron expressions 🪟🐛 client side validation of cron expressions Oct 13, 2022
.string()
.required("form.empty.error")
.test("validCron", "form.cronExpression.error", (expression) =>
!expression ? false : validateCronExpression(expression)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this check (!expression) be part of validateCronExpression to make this simpler?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah that's probably a good call. Yup.string.required() unfortunately doesn't narrow the type (it's a bug), so it's still string | undefined when it reaches the .test() method.

@@ -29,6 +29,7 @@ import { ValuesProps } from "hooks/services/useConnectionHook";
import { useCurrentWorkspace } from "services/workspaces/WorkspacesService";

import calculateInitialCatalog from "./calculateInitialCatalog";
import { validateCronExpression } from "./ScheduleField";
Copy link
Contributor

Choose a reason for hiding this comment

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

This utility is pretty generic, maybe it's best on src/utils/cron ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I can move it there. I wonder if over time src/utils might get bloated if we move all pure/generic functions there, but we can cross that bridge when we get there.

@@ -204,6 +203,11 @@ const ScheduleField: React.FC = () => {
onChange={(item: DropDownOptionDataItem) => onCronChange(item, field, form, "cronTimeZone")}
/>
</div>
{(form.errors?.scheduleData as ConnectionScheduleData)?.cron?.cronExpression && (
Copy link
Contributor

Choose a reason for hiding this comment

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

This value could be set as a var before the return so that it's easier to use:

const cronExpression = (form.errors?.scheduleData as ConnectionScheduleData)?.cron?.cronExpression

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it's kind of a nasty expression, I'll extract it to make the JSX cleaner.

Comment on lines 132 to 134
const cronValidationError = useMemo(() => {
return (errors?.scheduleData as ConnectionScheduleData)?.cron?.cronExpression;
}, [errors]);
Copy link
Collaborator

@timroes timroes Oct 19, 2022

Choose a reason for hiding this comment

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

If we want to get rid of the typecasting here (which imho looks a bit weird, given that TS thinks scheduleData is string), we could directly pull the error of that field (and get rid of the whole useMemo here):

  const [, { error: cronValidationError }] = useField("scheduleData.cron.cronExpression");

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice, that is cleaner, I'll use that. It still is not super type safe (useField() will accept any string without complaining) but it's not as ugly 😅

I think to get proper typing we would need to change the yup schema away from overloading scheduleData with the ambiguous .mixed().when(...), but I didn't want to blow up the PR.

Copy link
Collaborator

@timroes timroes left a comment

Choose a reason for hiding this comment

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

Have tested locally. Works for required and invalid cron expressions. Code LGTM, I left one suggestion to get rid of a typecast.

@josephkmh josephkmh merged commit 7682c99 into master Oct 19, 2022
@josephkmh josephkmh deleted the joey/sync-cron-expression-validation branch October 19, 2022 10:47
@josephkmh josephkmh restored the joey/sync-cron-expression-validation branch October 19, 2022 11:53
jhammarstedt pushed a commit to jhammarstedt/airbyte that referenced this pull request Oct 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/frontend Related to the Airbyte webapp area/platform issues related to the platform team/compose
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants