Skip to content

Commit

Permalink
feat: 上云周期任务添加最低任务间隔时间配置 --story=120737215
Browse files Browse the repository at this point in the history
  • Loading branch information
guohelu committed Nov 21, 2024
1 parent 692b69d commit 6fe22bf
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 0 deletions.
3 changes: 3 additions & 0 deletions config/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,9 @@ def check_engine_admin_permission(request, *args, **kwargs):
# 周期任务消息通知类型
PERIODIC_TASK_REMINDER_NOTIFY_TYPE = env.PERIODIC_TASK_REMINDER_NOTIFY_TYPE

# 周期任务最短时间间隔
PERIODIC_TASK_SHORTEST_TIME = env.PERIODIC_TASK_SHORTEST_TIME

# bk_audit
ENABLE_BK_AUDIT = True if env.BK_AUDIT_DATA_TOKEN else False
BK_AUDIT_SETTINGS = {
Expand Down
3 changes: 3 additions & 0 deletions env.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@
# 周期任务消息通知类型
PERIODIC_TASK_REMINDER_NOTIFY_TYPE = json.loads(os.getenv("PERIODIC_TASK_REMINDER_NOTIFY_TYPE", '["email"]'))

# 周期任务最短时间间隔
PERIODIC_TASK_SHORTEST_TIME = os.getenv("PERIODIC_TASK_SHORTEST_TIME", "")

# bk_audit
BK_AUDIT_ENDPOINT = os.getenv("BK_AUDIT_ENDPOINT", None)
BK_AUDIT_DATA_TOKEN = os.getenv("BK_AUDIT_DATA_TOKEN", None)
Expand Down
15 changes: 15 additions & 0 deletions gcloud/core/apis/drf/viewsets/periodic_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.response import Response

from gcloud.conf import settings
from gcloud import err_code
from gcloud.common_template.models import CommonTemplate
from gcloud.constants import COMMON, PERIOD_TASK_NAME_MAX_LENGTH, PROJECT
Expand Down Expand Up @@ -253,6 +254,11 @@ def destroy(self, request, *args, **kwargs):
def create(self, request, *args, **kwargs):
serializer = CreatePeriodicTaskSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
project = Project.objects.filter(id=serializer.validated_data["project"].id).first()
if settings.PERIODIC_TASK_SHORTEST_TIME:
result = PeriodicTask().inspect_time(request, serializer.validated_data["cron"], project.time_zone)
if not result:
raise ValidationException("The interval between tasks should be at least 30 minutes")
try:
self._handle_serializer(request, serializer)
instance = serializer.save()
Expand All @@ -272,6 +278,11 @@ def update(self, request, *args, **kwargs):
instance = self.get_object()
serializer = CreatePeriodicTaskSerializer(instance, data=request.data)
serializer.is_valid(raise_exception=True)
project = Project.objects.filter(id=serializer.validated_data["project"].id).first()
if settings.PERIODIC_TASK_SHORTEST_TIME:
result = PeriodicTask().inspect_time(request, serializer.validated_data["cron"], project.time_zone)
if not result:
raise ValidationException("The interval between tasks should be at least 30 minutes")
try:
self._handle_serializer(request, serializer)
instance = PeriodicTask.objects.update(instance, **serializer.validated_data)
Expand All @@ -293,6 +304,10 @@ def partial_update(self, request, *args, **kwargs):
with transaction.atomic():
if "cron" in serializer.validated_data:
project = Project.objects.filter(id=serializer.validated_data["project"]).first()
if settings.PERIODIC_TASK_SHORTEST_TIME:
result = instance.inspect_time(request, serializer.validated_data["cron"], project.time_zone)
if not result:
raise ValidationException("The interval between tasks should be at least 30 minutes")
instance.modify_cron(serializer.validated_data["cron"], project.time_zone)
if "constants" in serializer.validated_data:
instance.modify_constants(serializer.validated_data["constants"])
Expand Down
24 changes: 24 additions & 0 deletions gcloud/periodictask/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import logging

import ujson as json
import pytz
from croniter import croniter
from datetime import datetime, timedelta
from django.conf import settings
from django.db import models, transaction
from django.utils.translation import ugettext_lazy as _
Expand Down Expand Up @@ -254,6 +257,27 @@ def delete(self, using=None):
super(PeriodicTask, self).delete(using)
PeriodicTaskHistory.objects.filter(task=self).delete()

def inspect_time(self, request, cron, timezone=None):
try:
tz = pytz.timezone(timezone or "UTC")
except pytz.UnknownTimeZoneError:
return {"result": False, "data": None, "message": f"未知时区: {timezone}"}
result = True
if not request.user.is_superuser:
now_time = datetime.now(tz)
cron_expression = " ".join(list(cron.values()))
schedule_iter = croniter(cron_expression, now_time)

next_time_1 = schedule_iter.get_next(datetime)
next_time_2 = schedule_iter.get_next(datetime)

interval_difference = next_time_2 - next_time_1
shortest_time = int(settings.PERIODIC_TASK_SHORTEST_TIME)
if interval_difference < timedelta(minutes=shortest_time):
result = False

return result

def modify_cron(self, cron, timezone):
if self.task.enabled is False:
self.task.modify_cron(cron, timezone)
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,4 @@ opentelemetry-instrumentation-logging==0.30b1
opentelemetry-instrumentation-requests==0.30b1

bk-notice-sdk==1.3.0
croniter==0.3.29

0 comments on commit 6fe22bf

Please sign in to comment.