Exemple #1
0
def test_allow_execute_flow():
    FlowItem.delete().where(FlowItem.name == FLOW_NAME).execute()

    worktime = pendulum.datetime(2020, 1, 6, tz="Europe/Moscow")
    interval_timedelta = dt.timedelta(1)
    worktime_list = iter_range_datetime(
        start_time=worktime - dt.timedelta(3),
        end_time=worktime,
        timedelta=interval_timedelta,
    )

    FlowItem.create_items(
        flow_name=FLOW_NAME,
        worktime_list=worktime_list,
        status=Statuses.fatal_error,
        notebook_hash="",
    )
    assert (FlowItem.allow_execute_flow(
        FLOW_NAME, notebook_hash="", max_fatal_errors=3) is False)
    assert (FlowItem.allow_execute_flow(
        FLOW_NAME, notebook_hash="new", max_fatal_errors=3) is True)

    FlowItem.recreate_prev_items(
        flow_name=FLOW_NAME,
        worktime=worktime,
        offset_periods=10,
        interval_timedelta=interval_timedelta,
    )
    assert (FlowItem.allow_execute_flow(
        FLOW_NAME, notebook_hash="", max_fatal_errors=3) is True)
Exemple #2
0
    def create_missing_items(
        cls,
        flow_name: str,
        start_time: dt.datetime,
        end_time: dt.datetime,
        interval_timedelta: dt.timedelta,
    ) -> list["FlowItem"]:
        items = []
        for datetime_ in iter_range_datetime(start_time, end_time,
                                             interval_timedelta):
            try:
                item = cls.create(**{
                    cls.name.name: flow_name,
                    cls.worktime.name: datetime_
                })
            except peewee.IntegrityError:
                item = cls.get(cls.name == flow_name,
                               cls.worktime == datetime_)
            else:
                logger.info("Created missing worktime {} for {}", datetime_,
                            flow_name)

            items.append(item)

        return items
Exemple #3
0
    def __call__(
        self,
        start_period: dt.datetime,
        end_period: dt.datetime,
        *,
        async_mode: bool = False,
        dry_run: bool = False,
        **kwargs,
    ) -> Iterator[Union[dict, Optional[AsyncTaskT]]]:

        date_log = self._get_period_text(start_period, end_period)
        self.logger.update(self.name, filename=f"{date_log}.log", level=self.loglevel)
        self.logger.info("Start flow: %s  %s", self.name, date_log)

        datetime_list = iter_range_datetime(
            start_period, end_period, self.Work.interval_timedelta
        )

        self.items = self.Model.create_items(
            self.name,
            datetime_list,
            operator=FlowOperator.etl,
            data=self.operator_context.dict(exclude_unset=True),
        )

        log_data = {}
        try:
            for item in self.iterator(start_period, end_period, **kwargs):
                if isinstance(item, (SleepTask, TaskPool)):
                    if async_mode is False:
                        if isinstance(item, SleepTask):
                            time.sleep(item.sleep)

                        continue
                else:
                    log_data = item
                    self.Model.update_items(self.items, **log_data)
                    self.logger.debug("%s: %s", self.name, log_data)

                yield item

        except:
            self.logger.exception("Fail flow: %s  %s", self.name, date_log)
            self.send_notifications(
                **{
                    "status": FlowStatus.error,
                    "period": self._get_period_text(start_period, end_period),
                    **log_data,
                }
            )
            raise

        else:
            self.send_notifications(
                FlowStatus.success,
                period=self._get_period_text(start_period, end_period),
            )
        finally:
            self.Model.update_items(self.items)
            self.logger.info("End flow: %s  %s", self.name, date_log)
Exemple #4
0
    def current_worktime(self) -> dt.datetime:
        """
        Returns the work datetime at the moment.
        """
        end_time = pendulum.now(self.timezone)

        if self.start_datetime > end_time:
            start_time = self.start_datetime - self.interval_timedelta
            if start_time > end_time:
                raise ValueError(f"{start_time=} > {end_time=}")
        else:
            start_time = self.start_datetime

        worktime = list(
            iter_range_datetime(
                start_time=start_time,
                end_time=end_time,
                timedelta=self.interval_timedelta,
            ))[-1]

        if self.is_second_interval is False:
            worktime = worktime - self.interval_timedelta

        return worktime
    def current_worktime(self) -> dt.datetime:
        """
        Returns the work datetime at the moment.
        """
        end_time = pendulum.now(self.timezone).at(
            hour=self.start_datetime.hour,
            minute=self.start_datetime.minute,
            second=self.start_datetime.second,
        )
        if self.is_second_interval is False:
            end_time = end_time - self.interval_timedelta

        if self.start_datetime > end_time:
            start_time = self.start_datetime - self.interval_timedelta
        else:
            start_time = self.start_datetime

        return list(
            iter_range_datetime(
                start_time=start_time,
                end_time=end_time,
                timedelta=self.interval_timedelta,
            )
        )[-1]
Exemple #6
0
    def _iterator(
        self,
        start_period: dt.datetime,
        end_period: dt.datetime,
        *,
        dry_run: bool = False,
        **kwargs,
    ) -> Iterator[Union[dict, Optional[AsyncIterationT]]]:

        self.operator_context.start_period = start_period
        self.operator_context.end_period = end_period
        self.Load.update_context(self.operator_context)
        self.add_logger_file(dry_run)

        period_text = self._get_period_text(start_period, end_period)
        datetime_list = iter_range_datetime(start_period, end_period,
                                            self.Work.interval_timedelta)

        # TODO: Записи уже должны быть, их не надо создавать
        self.items = self.Model.create_items(
            self.notebook.name,
            datetime_list,
            **{
                self.Model.data.name:
                self.operator_context.dict(exclude_unset=True),
                self.Model.logpath.name:
                str(self.get_logfile_path().absolute()),
            },
        )

        log_data = {}
        try:
            self.logger.info("Start flow: {} {}", self.notebook.name,
                             period_text)

            for item in self(start_period,
                             end_period,
                             dry_run=dry_run,
                             **kwargs):
                if isinstance(item, dict):
                    log_data = item
                    self.Model.update_items(self.items, **log_data)
                    self.logger.info("{}: {}", self.notebook.name, log_data)

                if isinstance(item, (SleepIteration, NextIterationInPools)):
                    yield item

        except Exception:
            self.logger.exception("Fail flow: {}  {}", self.notebook.name,
                                  period_text)
            if dry_run is False:
                self.send_notifications(
                    **{
                        "status": Statuses.error,
                        "period": self._get_period_text(
                            start_period, end_period),
                        **log_data,
                    })
            raise

        else:
            if dry_run is False:
                self.send_notifications(
                    Statuses.success,
                    period=self._get_period_text(start_period, end_period),
                )

        finally:
            self.Model.update_items(self.items)
            self.logger.info("End flow: {}  {}", self.notebook.name,
                             period_text)