Skip to content

Commit

Permalink
fix: 修复错误并添加单侧 --story=120737215
Browse files Browse the repository at this point in the history
  • Loading branch information
guohelu committed Nov 21, 2024
1 parent 6fe22bf commit b14e135
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 20 deletions.
2 changes: 1 addition & 1 deletion env.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
# 周期任务消息通知类型
PERIODIC_TASK_REMINDER_NOTIFY_TYPE = json.loads(os.getenv("PERIODIC_TASK_REMINDER_NOTIFY_TYPE", '["email"]'))

# 周期任务最短时间间隔
# 周期任务最短时间间隔,以分钟为单位,例如:30
PERIODIC_TASK_SHORTEST_TIME = os.getenv("PERIODIC_TASK_SHORTEST_TIME", "")

# bk_audit
Expand Down
12 changes: 9 additions & 3 deletions gcloud/core/apis/drf/viewsets/periodic_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,9 @@ def create(self, request, *args, **kwargs):
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)
result = PeriodicTask().inspect_time(
request.user.is_superuser, serializer.validated_data["cron"], project.time_zone
)
if not result:
raise ValidationException("The interval between tasks should be at least 30 minutes")
try:
Expand All @@ -280,7 +282,9 @@ def update(self, request, *args, **kwargs):
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)
result = PeriodicTask().inspect_time(
request.user.is_superuser, serializer.validated_data["cron"], project.time_zone
)
if not result:
raise ValidationException("The interval between tasks should be at least 30 minutes")
try:
Expand All @@ -305,7 +309,9 @@ def partial_update(self, request, *args, **kwargs):
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)
result = instance.inspect_time(
request.user.is_superuser, 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)
Expand Down
33 changes: 19 additions & 14 deletions gcloud/periodictask/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import logging

import ujson as json
import pytz
from django_celery_beat.models import CrontabSchedule as DjangoCeleryBeatCrontabSchedule
from croniter import croniter
from datetime import datetime, timedelta
from django.conf import settings
Expand Down Expand Up @@ -257,23 +257,28 @@ 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}"}
def inspect_time(self, is_superuser, cron, timezone=None):
schedule, _ = DjangoCeleryBeatCrontabSchedule.objects.get_or_create(
minute=cron.get("minute", "*"),
hour=cron.get("hour", "*"),
day_of_week=cron.get("day_of_week", "*"),
day_of_month=cron.get("day_of_month", "*"),
month_of_year=cron.get("month_of_year", "*"),
timezone=timezone or "UTC",
)
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)
if not is_superuser:
cron_expression = (
f"{schedule.minute} {schedule.hour} {schedule.day_of_month} {schedule.month_of_year} "
f"{schedule.day_of_week}"
)
schedule_iter = croniter(cron_expression)

next_time_1 = schedule_iter.get_next(datetime)
next_time_2 = schedule_iter.get_next(datetime)
next_times = [schedule_iter.get_next(datetime) for _ in range(10)]
min_interval = min((next_times[i] - next_times[i - 1] for i in range(1, len(next_times))))

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

return result
Expand Down
11 changes: 10 additions & 1 deletion gcloud/tests/periodictask/models/test_periodic_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ def setUp(self):
template_id=uniqid(), name=self.task_template_name, creator=self.creator, snapshot=self.snapshot
)
self.template_version = "template_version"
task_template = TaskTemplate(project=self.project, pipeline_template=self.pipeline_template,)
task_template = TaskTemplate(
project=self.project,
pipeline_template=self.pipeline_template,
)
task_template.save()
self.template = task_template
self.task = self.create_a_task()
Expand Down Expand Up @@ -234,6 +237,12 @@ def test_delete(self):
PipelinePeriodicTask.DoesNotExist, PipelinePeriodicTask.objects.get, id=pipeline_periodic_task_id
)

def test_inspect_time(self):
self.cron = {"day_of_month": "*", "day_of_week": "*", "hour": "*", "minute": "*/30", "month_of_year": "*"}
self.timezone = "Asia/Shanghai"
self.periodic_task = self.task.inspect_time(is_superuser=0, cron=self.cron, timezone=self.timezone)
self.assertTrue(self.periodic_task)

def test_modify_constants(self):
expect_constants = copy.deepcopy(self.task.task.execution_data["constants"])
expect_constants["key_1"]["value"] = "val_3"
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,4 @@ opentelemetry-instrumentation-logging==0.30b1
opentelemetry-instrumentation-requests==0.30b1

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

0 comments on commit b14e135

Please sign in to comment.