Repository navigation
feat: enforce configurable minimum cron intervals #308
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -245,7 +245,12 @@ async def _custom_sources(org_id: uuid.UUID, session: AsyncSession) -> list[str] | |
|
|
||
| def _cron_interval_floor() -> int: | ||
| """Shortest interval between fires the scheduler can actually honour.""" | ||
| return max(POLL_INTERVAL_SECONDS, get_config().service.scheduler_interval_seconds) | ||
| settings = get_config().service | ||
| return max( | ||
| POLL_INTERVAL_SECONDS, | ||
| settings.scheduler_interval_seconds, | ||
| settings.min_cron_interval_seconds, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding |
||
| ) | ||
|
|
||
|
|
||
| def _cron_errors(trigger: CronTrigger) -> list[DraftValidationError]: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ | |
| model_validator, | ||
| ) | ||
| from pydantic.alias_generators import to_camel | ||
| from pydantic_core import PydanticCustomError | ||
|
|
||
| from openhands.automation.constants import MODEL_PROFILE_PATTERN | ||
| from openhands.automation.models import AutomationState | ||
|
|
@@ -28,6 +29,7 @@ | |
| verifier_schemes, | ||
| ) | ||
| from openhands.automation.utils.cron import ( | ||
| min_interval_seconds, | ||
| validate_cron_schedule as validate_cron_schedule_value, | ||
| validate_timezone_name, | ||
| ) | ||
|
|
@@ -68,7 +70,19 @@ class CronTrigger(BaseModel): | |
| @field_validator("schedule") | ||
| @classmethod | ||
| def validate_cron_schedule(cls, v: str) -> str: | ||
| return validate_cron_schedule_value(v) | ||
| schedule = validate_cron_schedule_value(v) | ||
|
|
||
| # Import lazily to keep the schema/config dependency one-way at import time. | ||
| from openhands.automation.config import get_config | ||
|
|
||
| floor = get_config().service.min_cron_interval_seconds | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The enforcement floor here is only
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This reads only |
||
| if floor > 0 and min_interval_seconds(schedule) < floor: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Raising
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Addressed in |
||
| raise PydanticCustomError( | ||
| "interval_too_short", | ||
| "Cron expression must have at least {floor} seconds between fires", | ||
| {"floor": floor}, | ||
| ) | ||
| return schedule | ||
|
|
||
| @field_validator("timezone") | ||
| @classmethod | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Including
min_cron_interval_secondsin the advertisedmax(...)only matches the create/update enforcement when this knob is the largest term. At the default0the schema validator performs no floor check at all, yet capabilities still advertisesmax(POLL_INTERVAL_SECONDS, scheduler_interval_seconds). Confirmed on this head: withAUTOMATION_SCHEDULER_INTERVAL_SECONDS=300and the knob unset,*/2 * * * *is accepted at create time while the advertised floor is 300. Routing enforcement through this same helper would close the gap this PR is meant to close.