Exemplo n.º 1
0
 def _raise_mysql_error(self, errclass, errno, errmsg):
     """Raise a MySQL error wrapped by SQLAlchemy."""
     error = errclass(errno, errmsg)
     wrapped = InterfaceError.instance(
         statement="SELECT COUNT(*) FROM table",
         params={},
         orig=error,
         dbapi_base_err=MySQLError,
     )
     raise wrapped
Exemplo n.º 2
0
def handle_qserv_exception(context):
    conn = context.connection.connection
    if hasattr(conn, "error") and context.original_exception.args[0] == -1:
        # Handle Qserv Errors where we return error codes above those
        # identified by the MySQLdb driver.
        # The MySQL driver, by default, returns a "whack" error code
        # if this is the case with error == -1.
        from _mysql_exceptions import InterfaceError as MysqlIError
        old_exc = context.sqlalchemy_exception
        orig = MysqlIError(conn.errno(), conn.error())
        return InterfaceError(old_exc.statement, old_exc.params, orig,
                              old_exc.connection_invalidated)
    pass
Exemplo n.º 3
0
    def test_execute_with_session_with_reconnection(self,
                                                    apply_and_flush_mock):
        function_mock = Mock()
        args = ()
        kwargs = {}

        broken_session = Mock()
        new_session = Mock()
        session_class_mock = Mock()
        session_class_mock.side_effect = [broken_session, new_session]

        apply_and_flush_mock.side_effect = [
            InterfaceError(None, None, None, None), sentinel
        ]

        result = db_manager._execute_with_session(session_class_mock,
                                                  function_mock, args, kwargs)

        expected_calls = [
            call(function_mock, broken_session, args, kwargs),
            call(function_mock, new_session, args, kwargs),
        ]
        self.assertEqual(apply_and_flush_mock.call_args_list, expected_calls)
        self.assertEqual(result, sentinel)
Exemplo n.º 4
0
    def test_retriable_exceptions(
        self,
        celery,
        redis,
        session,
        db_shared_session,
        metricsmock,
        errclass,
        errno,
        errmsg,
        backoff_sleep_mock,
    ):
        """Test database exceptions where the task should wait and try again."""

        obs = CellObservationFactory.build(radio=Radio.lte)
        shard = CellShard.shard_model(obs.cellid)
        cell = CellShardFactory.build(
            radio=obs.radio,
            mcc=obs.mcc,
            mnc=obs.mnc,
            lac=obs.lac,
            cid=obs.cid,
            samples=10,
            created=datetime(2019, 12, 5, tzinfo=UTC),
        )
        session.add(cell)
        session.commit()
        session.begin_nested()  # Protect test cell from task rollback

        error = errclass(errno, errmsg)
        wrapped = InterfaceError.instance(
            statement="SELECT COUNT(*) FROM cell_area",
            params={},
            orig=error,
            dbapi_base_err=MySQLError,
        )
        with mock.patch.object(CellUpdater,
                               "add_area_update",
                               side_effect=[wrapped, None]):
            self._queue_and_update(celery, [obs], update_cell)
            assert CellUpdater.add_area_update.call_count == 2
            backoff_sleep_mock.assert_called_once()

        cells = session.query(shard).all()
        assert len(cells) == 1
        self.check_statcounter(redis, StatKey.cell, 1)

        # The existing cell record was updated
        cell = cells[0]
        assert cell.samples == 11
        assert cell.created == datetime(2019, 12, 5, tzinfo=UTC)
        self.check_statcounter(redis, StatKey.unique_cell, 0)

        # Assert generated metrics are correct
        metricsmock.assert_incr_once("data.observation.insert",
                                     value=1,
                                     tags=["type:cell"])
        metricsmock.assert_incr_once("data.station.confirm",
                                     value=1,
                                     tags=["type:cell"])
        metricsmock.assert_timing_once("task", tags=["task:data.update_cell"])
        metricsmock.assert_incr_once("data.station.dberror",
                                     tags=["type:cell",
                                           "errno:%s" % errno])
Exemplo n.º 5
0
    def test_retriable_exceptions(self, celery, redis, session, db,
                                  metricsmock, errclass, errno, errmsg):
        """Test database exceptions where the task should wait and try again."""

        obs = CellObservationFactory.build(radio=Radio.lte)
        shard = CellShard.shard_model(obs.cellid)
        cell = CellShardFactory.build(
            radio=obs.radio,
            mcc=obs.mcc,
            mnc=obs.mnc,
            lac=obs.lac,
            cid=obs.cid,
            samples=10,
            created=datetime(2019, 12, 5, tzinfo=UTC),
        )
        session.add(cell)
        session.commit()
        # TODO: Find a more elegant way to do this
        db.tests_task_use_savepoint = True

        error = errclass(errno, errmsg)
        wrapped = InterfaceError.instance(
            statement="SELECT COUNT(*) FROM cell_area",
            params={},
            orig=error,
            dbapi_base_err=MySQLError,
        )
        with mock.patch.object(
                CellUpdater, "add_area_update", side_effect=[
                    wrapped, None
                ]), mock.patch("ichnaea.data.station.time.sleep") as sleepy:
            self._queue_and_update(celery, [obs], update_cell)
            assert CellUpdater.add_area_update.call_count == 2
            sleepy.assert_called_once_with(1)

        del db.tests_task_use_savepoint

        cells = session.query(shard).all()
        assert len(cells) == 1
        self.check_statcounter(redis, StatKey.cell, 1)

        # The existing cell record was updated
        cell = cells[0]
        assert cell.samples == 11
        assert cell.created == datetime(2019, 12, 5, tzinfo=UTC)
        self.check_statcounter(redis, StatKey.unique_cell, 0)

        # Assert generated metrics are correct
        assert metricsmock.has_record("incr",
                                      "data.observation.insert",
                                      value=1,
                                      tags=["type:cell"])
        assert metricsmock.has_record("incr",
                                      "data.station.confirm",
                                      value=1,
                                      tags=["type:cell"])
        assert metricsmock.has_record("timing",
                                      "task",
                                      tags=["task:data.update_cell"])
        assert metricsmock.has_record(
            "incr",
            "data.station.dberror",
            value=1,
            tags=["type:cell", "errno:%s" % errno],
        )