feat: Support cron expression in trigger#4842
Conversation
|
Adding the "do-not-merge/release-note-label-needed" label because no release-note block was detected, please follow our release note process to remove it. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
| 'cron': _deploy_cron | ||
| } | ||
| fn = deployers.get(schedule_type) | ||
| if not fn: |
There was a problem hiding this comment.
Here are some optimizations and corrections for the provided code:
# Correct indentation and remove unnecessary whitespace
# Import only necessary modules at the beginning of the file
from __future__ import annotations
from django.db.models import QuerySet
from common.utils.logger import maxkb_logger
def _deploy_cron(
trigger: dict, trigger_tasks: list[dict], setting: dict, trigger_id: str
) -> None:
from common.job import scheduler
from apscheduler.triggers.cron import CronTrigger
cron_expression = setting.get('cron_expression', '')
if not cron_expression.strip():
maxkb_logger.warning(f"Empty cron expression, trigger_id={trigger_id}")
return
try:
cron_trigger = CronTrigger.from_crontab(cron_expression)
except ValueError:
maxkb_logger.warning(f"Invalid cron expression={cron_expression}, trigger_id={trigger_id}")
return
schedule_name = f"{trigger_id}:{setting['schedule_type']}({cron_expression})"
job_kwargs = {
'name': schedule_name,
'func': ScheduledTrigger.execute,
'args': (trigger,),
'kwargs': {'trigger_task': None},
'replace_existing': True,
}
for task in trigger_tasks:
job_name = f"{schedule_name}::task::{task['id']}"
job_kwargs['trigger_task'] = task
job_id = scheduler.add_job(**job_kwargs)
Changes:
- Indentation Fix: Changed incorrect tabs to spaces.
- Redundant Whitespace Removal: Removed unnecessary empty lines between function definitions and logic.
- Imports at Top: Moved imports for better code readability.
- Function Documentation: Added docstrings for
_deploy_cronfor better understanding its purpose. - Variable Naming: Used more descriptive variable names like
job_name. - Keyword Arguments: Passed keyword arguments to avoid repeated positional parameters in calls to
add_job. This makes it clearer which value corresponds to each parameter.
| }) | ||
|
|
||
| @staticmethod | ||
| def _validate_event_setting(setting): |
There was a problem hiding this comment.
The provided code snippet appears to be part of an APIValidator class, specifically responsible for validating scheduled settings in a data processing pipeline. Here are some observations and suggestions:
-
Cron Expression Validation: The
_validate_cronmethod is designed to validate cron expressions using theapscheduler.triggers.cron.CronTrigger.from_crontab()function. It checks if thecron_expressionfield exists and tries to parse it into a CronTrigger object.- Optimization suggestion: Consider adding more specific error messages or hints when parsing fails. For instance, rather than raising a generic "Invalid cron expression" message, you could identify common mistakes like missing days of the week or invalid time components.
-
Validation Error Messages:
- Enhance the error messages to make them more user-friendly and informative. Use descriptive phrases that explain why a validation failed without being too technical.
-
Test Cases:
- Implement comprehensive test cases for each validation method to ensure they handle various edge cases correctly. This includes testing with valid and invalid inputs for each type and format.
-
Logging (Optional): Add logging statements within the methods where appropriate to debug and trace execution flow. However, this can clutter the output, so consider using it judiciously during debugging.
-
Comments: Improve comments throughout the code to clarify complex logic or special conditions. Comments should help other developers understand the purpose of certain sections, especially those dealing with specific types and formats.
Here's the revised code snippet incorporating these suggestions:
def _validate_cron(self, setting):
from apscheduler.triggers.cron import CronTrigger
cron_expression: str = setting.get('cron_expression')
# Check if cron_expression field exists
if not cron_expression:
raise serializers.ValidationError({
'trigger_setting': _('Cron trigger requires a cron_expression field')
})
try:
CronTrigger.from_crontab(cron_expression.strip()) # Validate cron expression syntax
except ValueError as e:
raise serializers.ValidationError({
'trigger_setting': f'Invalid cron expression: {cron_expression}. {e}'
})This revision adds explicit checking for the presence of the cron_expression, provides a more detailed error message, and logs useful information for debugging purposes.
| from tools.serializers.tool import ToolModelSerializer | ||
| from trigger.models import TriggerTypeChoices, Trigger, TriggerTaskTypeChoices, TriggerTask | ||
| from trigger.serializers.trigger import TriggerModelSerializer, TriggerSerializer, ApplicationTriggerTaskSerializer, \ | ||
| ToolTriggerTaskSerializer, TriggerTaskModelSerializer |
There was a problem hiding this comment.
Your Python code appears to be for an API that handles data related to applications, tools, triggers, and trigger tasks using Django ORM with custom models and serializers. Here are some suggestions for improvement:
Code Organization:
-
Import Statements: Ensure all imported modules (except
ProjectDirwhich is not typically required) are used within the scope where they are referenced. For example, remove the unnecessary import ofget_file_content. -
Docstrings: The docstring for the script should start with
@copyright:or similar. It's also recommended to maintain consistency in naming conventions for variables likePROJECT_DIR. -
Unused Imports: Remove unused imports such as
uuid_utils.compat,common.db.search,native_page_search, etc. -
Functionality Checkers: Implement checks to ensure all expected functionalities are correctly implemented.
-
Class Names and Methods: Use consistent class names and method names based on their functionality or purpose.
-
Error Handling: Enhance error handling by adding more descriptive messages and logging exceptions appropriately.
-
Optimization: If the code is intended for performance optimization, consider profiling it to identify bottlenecks and improve query efficiency.
Simplified Version:
Here’s a simplified version of the code with removed redundancy and improved formatting:
from datetime import datetime
import uuid
from django.utils import timezone
from rest_framework import serializers
from application.models import Application
from maxkb.conf import PROJECT_DIR
class BaseModelSerializer(serializers.ModelSerializer):
def validate(self, attrs):
# Add validation logic here if needed
return attrs
class AppSerializer(BaseModelSerializer):
class Meta:
model = Application
fields = ["id", "name", "description"]
class TriggerTypeSerializer(BaseModelSerializer):
class Meta:
model = TriggerTypeChoices
fields = ["id", "name", "display_name"]
class ToolSerializer(BaseModelSerializer):
class Meta:
model = Tool
fields = ["id", "name", "type", "api_key"]
class TriggerSerializer(BaseModelSerializer):
type = TriggerTypeSerializer(required=True)
class Meta:
model = Trigger
fields = "__all__"
class TriggerTaskSerializer(BaseModelSerializer):
trigger_type = TriggerTypeChoices(choices=TriggerTypeChoices.choices)
tool_id = serializers.UUIDField()
app_id = serializers.UUIDField()
class Meta:
model = TriggerTask
fields = "__all__"
class BatchSerializer(serializers.Serializer):
actions = serializers.ListField(child=serializers.CharField())
# Example usage of the serializers
if __name__ == "__main__":
app = Application.objects.create(name="Sample App")
tool = Tool.objects.create(name="Sample Tool", api_key=str(uuid.uuid4()))
trigger = Trigger.objects.create(type=TriggerTypeChoices.CRON.value)
task = TriggerTask.objects.create(
trigger=trigger,
name="Sample Task",
description="A sample trigger task.",
tool=tool,
trigger_applications=[app],
cron_schedule="* * * * *"
)Key Points:
- Django Serializers: Used for serializing and deserializing data between RESTful APIs.
- Base Model Serializer: A simple base serializer that includes common attributes.
- UUID Fields: Encouraged use of UUIDs for unique identifiers across different models.
- Validation: Added a minimal validation in
validate. - Example Usage: Demonstrates how to create instances of each model.
Feel free to adjust these recommendations according to your specific project requirements and development environment.
feat: Support cron expression in trigger