Files
superset2/superset/tasks/scheduler.py
Daniel Vaz Gaspar 1e3aaab590 fix(reports): validator_config, report state machine, working_timeout (#11890)
* fix(reports): expect more exceptions and fix validator config

* use a state pattern on command reports

* use a state pattern on command reports continue

* fix multiple heads

* fix unittests

* add more tests

* fix api tests after enum rename

* fix alembic multiple heads

* fix tests

* fix fixture cleanup

* fix mysql tests

* fix initial and not found state

* fix schema, and private public methods, addressing comments

* add new col to the API
2020-12-09 18:19:07 +00:00

73 lines
2.8 KiB
Python

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import logging
from datetime import datetime, timedelta
from typing import Iterator
import croniter
from superset.commands.exceptions import CommandException
from superset.extensions import celery_app
from superset.reports.commands.execute import AsyncExecuteReportScheduleCommand
from superset.reports.commands.log_prune import AsyncPruneReportScheduleLogCommand
from superset.reports.dao import ReportScheduleDAO
from superset.utils.celery import session_scope
logger = logging.getLogger(__name__)
def cron_schedule_window(cron: str, window_size: int = 10) -> Iterator[datetime]:
utc_now = datetime.utcnow()
start_at = utc_now - timedelta(seconds=1)
stop_at = utc_now + timedelta(seconds=window_size)
crons = croniter.croniter(cron, start_at)
for schedule in crons.all_next(datetime):
if schedule >= stop_at:
break
yield schedule
@celery_app.task(name="reports.scheduler")
def scheduler() -> None:
"""
Celery beat main scheduler for reports
"""
with session_scope(nullpool=True) as session:
active_schedules = ReportScheduleDAO.find_active(session)
for active_schedule in active_schedules:
for schedule in cron_schedule_window(active_schedule.crontab):
logger.info(
"Scheduling alert %s eta: %s", active_schedule.name, schedule
)
execute.apply_async((active_schedule.id, schedule,), eta=schedule)
@celery_app.task(name="reports.execute")
def execute(report_schedule_id: int, scheduled_dttm: datetime) -> None:
try:
AsyncExecuteReportScheduleCommand(report_schedule_id, scheduled_dttm).run()
except CommandException as ex:
logger.error("An exception occurred while executing the report: %s", ex)
@celery_app.task(name="reports.prune_log")
def prune_log() -> None:
try:
AsyncPruneReportScheduleLogCommand().run()
except CommandException as ex:
logger.error("An exception occurred while pruning report schedule logs: %s", ex)