Skip to content

Commit

Permalink
Adds MAX_RRULE_LENGTH (#7762)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakekaplan authored and masonmenges committed Jan 10, 2023
1 parent 0684048 commit 33201e5
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
3 changes: 3 additions & 0 deletions docs/concepts/schedules.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ schedule:
rrule: 'FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20240730T040000Z'
```

!!! info "Max RRule length"
Note the max supported character length of an `rrulestr` is 6500 characters

!!! info "Daylight saving time considerations"
Note that as a calendar-oriented standard, `RRules` are sensitive to the initial timezone provided. A 9am daily schedule with a DST-aware start date will maintain a local 9am time through DST boundaries. A 9am daily schedule with a UTC start date will maintain a 9am UTC time.

Expand Down
7 changes: 7 additions & 0 deletions src/prefect/orion/schemas/schedules.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from prefect.orion.utilities.schemas import DateTimeTZ, PrefectBaseModel

MAX_ITERATIONS = 1000
# approx. 1 years worth of RDATEs + buffer
MAX_RRULE_LENGTH = 6500


def _prepare_scheduling_start_and_end(
Expand Down Expand Up @@ -394,6 +396,11 @@ def validate_rrule_str(cls, v):
# rrules errors are a mix of cryptic and informative
# so reraise to be clear that the string was invalid
raise ValueError(f'Invalid RRule string "{v}": {exc}')
if len(v) > MAX_RRULE_LENGTH:
raise ValueError(
f'Invalid RRule string "{v[:40]}..."\n'
f"Max length is {MAX_RRULE_LENGTH}, got {len(v)}"
)
return v

@classmethod
Expand Down
17 changes: 10 additions & 7 deletions tests/orion/schemas/test_schedules.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from prefect.orion.schemas.schedules import (
MAX_ITERATIONS,
MAX_RRULE_LENGTH,
CronSchedule,
IntervalSchedule,
RRuleSchedule,
Expand Down Expand Up @@ -634,13 +635,6 @@ async def test_rrule_returns_nothing_before_dtstart(self):
dates = await s.get_dates(5, start=pendulum.now("UTC"))
assert dates == [pendulum.datetime(2030, 1, 1).add(days=i) for i in range(5)]

async def test_rrule_returns_nothing_before_dtstart(self):
s = RRuleSchedule.from_rrule(
rrule.rrule(freq=rrule.DAILY, dtstart=pendulum.datetime(2030, 1, 1))
)
dates = await s.get_dates(5, start=pendulum.now("UTC"))
assert dates == [pendulum.datetime(2030, 1, 1).add(days=i) for i in range(5)]

async def test_rrule_validates_rrule_str(self):
# generic validation error
with pytest.raises(ValidationError, match="(Invalid RRule string)"):
Expand All @@ -654,6 +648,15 @@ async def test_rrule_validates_rrule_str(self):
with pytest.raises(ValidationError, match="(invalid 'FREQ': DAILYBAD)"):
RRuleSchedule(rrule="FREQ=DAILYBAD")

async def test_rrule_max_rrule_len(self):
start = datetime(2000, 1, 1)
s = "RDATE:" + ",".join(
[start.add(days=i).format("YMMDD") + "T000000Z" for i in range(365 * 3)]
)
assert len(s) > MAX_RRULE_LENGTH
with pytest.raises(ValidationError, match="Max length"):
RRuleSchedule(rrule=s)

async def test_rrule_schedule_handles_complex_rrulesets(self):
s = RRuleSchedule(
rrule="DTSTART:19970902T090000\n"
Expand Down

0 comments on commit 33201e5

Please sign in to comment.