Skip to content

Commit

Permalink
feat(core): support for nickname on schedule
Browse files Browse the repository at this point in the history
close #614
  • Loading branch information
tchiotludo committed Aug 1, 2022
1 parent 00078ac commit 3e999cf
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@
},
full = true
),
@Example(
title = "A schedule with a nickname",
code = {
"triggers:",
" - id: schedule",
" type: io.kestra.core.models.triggers.types.Schedule",
" cron: \"@hourly\"",
},
full = true
),
@Example(
title = "A schedule that run only the first monday on every month at 11 AM",
code = {
Expand All @@ -74,7 +84,7 @@
" cron: \"0 11 * * 1\"",
" scheduleConditions:",
" - id: monday",
" date: \"{{ trigger.date }}\"" +
" date: \"{{ trigger.date }}\"",
" dayOfWeek: \"MONDAY\"",
" dayInMonth: \"FIRST\"",
},
Expand All @@ -84,19 +94,41 @@

)
public class Schedule extends AbstractTrigger implements PollingTriggerInterface, TriggerOutput<Schedule.Output> {
private static final CronParser CRON_PARSER = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX));
public static final CronParser CRON_PARSER = new CronParser(CronDefinitionBuilder.defineCron()
.withMinutes().withValidRange(0, 59).withStrictRange().and()
.withHours().withValidRange(0, 23).withStrictRange().and()
.withDayOfMonth().withValidRange(1, 31).withStrictRange().and()
.withMonth().withValidRange(1, 12).withStrictRange().and()
.withDayOfWeek().withValidRange(0, 7).withMondayDoWValue(1).withIntMapping(7, 0).withStrictRange().and()
.withSupportedNicknameYearly()
.withSupportedNicknameAnnually()
.withSupportedNicknameMonthly()
.withSupportedNicknameWeekly()
.withSupportedNicknameDaily()
.withSupportedNicknameMidnight()
.withSupportedNicknameHourly()
.instance()
);

@NotNull
@CronExpression
@Schema(
title = "the cron expression you need tyo ",
description = "a standard [unix cron expression](https://en.wikipedia.org/wiki/Cron) without second."
title = "the cron expression",
description = "a standard [unix cron expression](https://en.wikipedia.org/wiki/Cron) without second.\n" +
"Can also be a cron extensions / nicknames:\n" +
"* `@yearly`\n" +
"* `@annually`\n" +
"* `@monthly`\n" +
"* `@weekly`\n" +
"* `@daily`\n" +
"* `@midnight`\n" +
"* `@hourly`"
)
private String cron;

@Schema(
title = "Backfill options in order to fill missing previous past date",
description = "Kestra will handle optionnaly a backfill. The concept of backfill is the replay the missing schedule because we create the flow later.\n" +
description = "Kestra will handle optionally a backfill. The concept of backfill is the replay the missing schedule because we create the flow later.\n" +
"\n" +
"Backfill will do all schedules between define date & current date and will start after the normal schedule."
)
Expand Down Expand Up @@ -189,8 +221,6 @@ public Optional<Execution> evaluate(ConditionContext conditionContext, TriggerCo
return Optional.empty();
}



// inject outputs variables for scheduleCondition
conditionContext = conditionContext(conditionContext, output);

Expand All @@ -205,7 +235,6 @@ public Optional<Execution> evaluate(ConditionContext conditionContext, TriggerCo
output = this.trueOutputWithCondition(executionTime, conditionContext, output);
}


Map<String, Object> inputs = new HashMap<>();
if (this.inputs != null) {
for (Map.Entry<String, String> entry: this.inputs.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

@Factory
public class ValidationFactory {
private static final CronParser CRON_PARSER = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.UNIX));
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

@Singleton
Expand Down Expand Up @@ -46,7 +45,7 @@ ConstraintValidator<CronExpression, CharSequence> cronExpressionValidator() {
}

try {
Cron parse = CRON_PARSER.parse(value.toString());
Cron parse = io.kestra.core.models.triggers.types.Schedule.CRON_PARSER.parse(value.toString());
parse.validate();
} catch (IllegalArgumentException e) {
context.messageTemplate("invalid cron expression '({validatedValue})': " + e.getMessage());
Expand All @@ -58,7 +57,6 @@ ConstraintValidator<CronExpression, CharSequence> cronExpressionValidator() {
};
}


@Singleton
ConstraintValidator<Schedule, io.kestra.core.models.triggers.types.Schedule> scheduleValidator() {
return (value, annotationMetadata, context) -> {
Expand All @@ -76,7 +74,6 @@ ConstraintValidator<Schedule, io.kestra.core.models.triggers.types.Schedule> sch
};
}


@Singleton
ConstraintValidator<JsonString, String> jsonStringValidator() {
return (value, annotationMetadata, context) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ void conditionsWithBackfill() throws Exception {
}
}


@SuppressWarnings("unchecked")
@Test
void lateMaximumDelay() throws Exception {
Expand All @@ -328,6 +327,28 @@ void lateMaximumDelay() throws Exception {

}

@SuppressWarnings("unchecked")
@Test
void hourly() throws Exception {
Schedule trigger = Schedule.builder()
.cron("@hourly")
.build();

ZonedDateTime date = ZonedDateTime.now().minusHours(1).withMinute(0).withSecond(0).withNano(0);


Optional<Execution> evaluate = trigger.evaluate(
conditionContext(),
TriggerContext.builder()
.date(date)
.build()
);

assertThat(evaluate.isPresent(), is(true));
var vars = (Map<String, String>) evaluate.get().getVariables().get("schedule");
assertThat(dateFromVars(vars.get("date"), date), is(date));
}

private ConditionContext conditionContext() {
return ConditionContext.builder()
.runContext(runContextFactory.of())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,15 @@ void cronValidation() throws Exception {
assertThat(modelValidator.isValid(build).isPresent(), is(true));
assertThat(modelValidator.isValid(build).get().getMessage(), containsString("invalid cron expression"));
}

@Test
void nicknameValidation() throws Exception {
Schedule build = Schedule.builder()
.id(IdUtils.create())
.type(Schedule.class.getName())
.cron("@hourly")
.build();

assertThat(modelValidator.isValid(build).isEmpty(), is(true));
}
}

0 comments on commit 3e999cf

Please sign in to comment.