Example #1
0
def test_execute_query_succeeded_with_retries(mocker: MockFixture,
                                              app_context: None) -> None:
    from superset.reports.commands.alert import AlertCommand, AlertQueryError

    execute_query_mock = mocker.patch(
        "superset.reports.commands.alert.AlertCommand._execute_query")

    query_executed_count = 0
    # Should match the value defined in superset_test_config.py
    expected_max_retries = 3

    def _mocked_execute_query() -> pd.DataFrame:
        nonlocal query_executed_count
        query_executed_count += 1

        if query_executed_count < expected_max_retries:
            raise AlertQueryError()
        else:
            return pd.DataFrame([{"sample_col": 0}])

    execute_query_mock.side_effect = _mocked_execute_query
    execute_query_mock.__name__ = "mocked_execute_query"

    command = AlertCommand(report_schedule=mocker.Mock())

    command.validate()

    assert execute_query_mock.call_count == expected_max_retries
Example #2
0
 def next(self) -> None:
     self.set_state_and_log(ReportState.WORKING)
     try:
         # If it's an alert check if the alert is triggered
         if self._report_schedule.type == ReportScheduleType.ALERT:
             if not AlertCommand(self._report_schedule).run():
                 self.set_state_and_log(ReportState.NOOP)
                 return
         self.send()
         self.set_state_and_log(ReportState.SUCCESS)
     except CommandException as first_ex:
         self.set_state_and_log(ReportState.ERROR,
                                error_message=str(first_ex))
         # TODO (dpgaspar) convert this logic to a new state eg: ERROR_ON_GRACE
         if not self.is_in_error_grace_period():
             try:
                 self.send_error(
                     f"Error occurred for {self._report_schedule.type}:"
                     f" {self._report_schedule.name}",
                     str(first_ex),
                 )
                 self.set_state_and_log(
                     ReportState.ERROR,
                     error_message=REPORT_SCHEDULE_ERROR_NOTIFICATION_MARKER,
                 )
             except CommandException as second_ex:
                 self.set_state_and_log(ReportState.ERROR,
                                        error_message=str(second_ex))
         raise first_ex
Example #3
0
    def next(self) -> None:
        if self._report_schedule.type == ReportScheduleType.ALERT:
            if self.is_in_grace_period():
                self.set_state_and_log(
                    ReportState.GRACE,
                    error_message=str(ReportScheduleAlertGracePeriodError()),
                )
                return
            self.set_state_and_log(ReportState.WORKING)
            try:
                if not AlertCommand(self._report_schedule).run():
                    self.set_state_and_log(ReportState.NOOP)
                    return
            except CommandException as ex:
                self.send_error(
                    f"Error occurred for {self._report_schedule.type}:"
                    f" {self._report_schedule.name}",
                    str(ex),
                )
                self.set_state_and_log(
                    ReportState.ERROR,
                    error_message=REPORT_SCHEDULE_ERROR_NOTIFICATION_MARKER,
                )
                raise ex

        try:
            self.send()
            self.set_state_and_log(ReportState.SUCCESS)
        except CommandException as ex:
            self.set_state_and_log(ReportState.ERROR, error_message=str(ex))
Example #4
0
def test_execute_query_succeeded_no_retry(mocker: MockFixture,
                                          app_context: None) -> None:

    from superset.reports.commands.alert import AlertCommand

    execute_query_mock = mocker.patch(
        "superset.reports.commands.alert.AlertCommand._execute_query",
        side_effect=lambda: pd.DataFrame([{
            "sample_col": 0
        }]),
    )

    command = AlertCommand(report_schedule=mocker.Mock())

    command.validate()

    assert execute_query_mock.call_count == 1
Example #5
0
def test_execute_query_failed_no_retry(mocker: MockFixture,
                                       app_context: None) -> None:
    from superset.reports.commands.alert import AlertCommand, AlertQueryTimeout

    execute_query_mock = mocker.patch(
        "superset.reports.commands.alert.AlertCommand._execute_query")

    def _mocked_execute_query() -> None:
        raise AlertQueryTimeout

    execute_query_mock.side_effect = _mocked_execute_query
    execute_query_mock.__name__ = "mocked_execute_query"

    command = AlertCommand(report_schedule=mocker.Mock())

    try:
        command.validate()
    except AlertQueryTimeout:
        pass

    assert execute_query_mock.call_count == 1
Example #6
0
def test_execute_query_failed_max_retries(mocker: MockFixture,
                                          app_context: None) -> None:
    from superset.reports.commands.alert import AlertCommand, AlertQueryError

    execute_query_mock = mocker.patch(
        "superset.reports.commands.alert.AlertCommand._execute_query")

    def _mocked_execute_query() -> None:
        raise AlertQueryError

    execute_query_mock.side_effect = _mocked_execute_query
    execute_query_mock.__name__ = "mocked_execute_query"

    command = AlertCommand(report_schedule=mocker.Mock())

    try:
        command.validate()
    except AlertQueryError:
        pass

    # Should match the value defined in superset_test_config.py
    assert execute_query_mock.call_count == 3
Example #7
0
 def next(self) -> None:
     self.set_state_and_log(ReportState.WORKING)
     try:
         # If it's an alert check if the alert is triggered
         if self._report_schedule.type == ReportScheduleType.ALERT:
             if not AlertCommand(self._report_schedule).run():
                 self.set_state_and_log(ReportState.NOOP)
                 return
         self.send()
         self.set_state_and_log(ReportState.SUCCESS)
     except CommandException as ex:
         self.set_state_and_log(ReportState.ERROR, error_message=str(ex))
         raise ex
Example #8
0
    def run(self) -> None:
        with session_scope(nullpool=True) as session:
            try:
                start_dttm = datetime.utcnow()
                self.validate(session=session)
                if not self._model:
                    raise ReportScheduleExecuteUnexpectedError()
                self.set_state_and_log(session, start_dttm, ReportLogState.WORKING)
                # If it's an alert check if the alert is triggered
                if self._model.type == ReportScheduleType.ALERT:
                    if not AlertCommand(self._model).run():
                        self.set_state_and_log(session, start_dttm, ReportLogState.NOOP)
                        return

                self._send(self._model)

                # Log, state and TS
                self.set_state_and_log(session, start_dttm, ReportLogState.SUCCESS)
            except ReportScheduleAlertGracePeriodError as ex:
                self.set_state_and_log(
                    session, start_dttm, ReportLogState.NOOP, error_message=str(ex)
                )
            except ReportSchedulePreviousWorkingError as ex:
                self.create_log(
                    session,
                    start_dttm,
                    datetime.utcnow(),
                    state=ReportLogState.ERROR,
                    error_message=str(ex),
                )
                session.commit()
                raise
            except CommandException as ex:
                self.set_state_and_log(
                    session, start_dttm, ReportLogState.ERROR, error_message=str(ex)
                )
                # We want to actually commit the state and log inside the scope
                session.commit()
                raise