Exemple #1
0
    def test_retry_database_read_errors(
        self, database_type: DatabaseType, caplog: LogCaptureFixture, monkeypatch: MonkeyPatch
    ) -> None:
        caplog.set_level(logging.DEBUG)
        database = Database(database_type)

        mocked_query = Mock(side_effect=[pyodbc.OperationalError("Error 1"), pyodbc.OperationalError("Error 2"), True])
        monkeypatch.setattr(Session, "query", mocked_query)

        @retry_database_read_errors
        def query_with_retry() -> bool:
            with database.transaction_context() as session:
                return session.query()  # type: ignore

        assert query_with_retry()
        assert mocked_query.call_count == 3
        assert (
            "Error 'Error 1' occurred while running query_with_retry. Trying again 2 more time(s) in 1 second(s)."
            in caplog.messages
        )
        assert f"Error during {database} operation, transaction was rolled-back: Error 1" in caplog.messages
        assert (
            "Error 'Error 2' occurred while running query_with_retry. Trying again 1 more time(s) in 1 second(s)."
            in caplog.messages
        )
        assert f"Error during {database} operation, transaction was rolled-back: Error 2" in caplog.messages
Exemple #2
0
    async def _run_operation(self, func, *args, **kwargs):
        # execute func in thread pool of attached to cursor connection
        if not self._conn:
            raise pyodbc.OperationalError('Cursor is closed.')

        try:
            result = await self._conn._execute(func, *args, **kwargs)
            return result
        except pyodbc.Error as e:
            if self._conn and _is_conn_close_error(e):
                await self._conn.close()
            raise
    def test_error_10004_logging(self, m_log):
        cursor = self.get_cursor()
        m_execute = mock.Mock()
        m_execute.side_effect = pyodbc.OperationalError()

        with mock.patch.object(cursor, 'execute', m_execute):
            sql = 'SELECT count(*) AS count_1'
            params = (1, 2, 3)
            with pytest.raises(pyodbc.OperationalError):
                self.__dialect__.do_execute(cursor, sql, params)

        m_log.error.assert_called_once_with(
            'pyodbc OperationalError. Full statement: SELECT count(*) AS count_1'
            '\n Params: (1, 2, 3)')
def test_conexion_fallida():
    # Given
    driver = 'dummy_driver'
    servidor = 'dummy_servidor'
    base_datos = 'dummy_base_datos'
    usuario = 'dummy_usuario'
    contraseña = 'dummy_contraseña'
    pyodbc.connect = Mock(side_effect=pyodbc.OperationalError('error code'))

    # When
    with pytest.raises(pyodbc.OperationalError) as error:
        ClienteBaseDatos(driver, servidor, base_datos, usuario, contraseña)

    # Then
    pyodbc.connect.assert_called_once() 
    pyodbc.connect.assert_called_with("DRIVER={dummy_driver};SERVER=dummy_servidor;DATABASE=dummy_base_datos;UID=dummy_usuario;PWD=dummy_contraseña")
    assert error.value.args[0] == 'error code'
Exemple #5
0
    def test_retry_and_fail(
        self, database_type: DatabaseType, monkeypatch: MonkeyPatch, caplog: LogCaptureFixture
    ) -> None:
        monkeypatch.setattr(master_config, "db_connection_attempts", 3)
        monkeypatch.setattr(master_config, "db_connection_retry_sleep_seconds", 0.01)

        monkeypatch.setattr(pyodbc, "connect", Mock(side_effect=pyodbc.OperationalError("Always fails!")))

        with pytest.raises(DatabaseConnectionFailure):
            with caplog.at_level(logging.DEBUG):
                database = Database(database_type)
                database.get_existing_table_names()  # Run something that explicitly connects to the database

        assert caplog.messages == [
            f"Trying to connect to {database_type.name} database, attempt #1",
            f"Unsuccessful attempt #1 to connect to {database_type.name} database: Always fails!",
            "Waiting 0.01 seconds before next connection attempt",
            f"Trying to connect to {database_type.name} database, attempt #2",
            f"Unsuccessful attempt #2 to connect to {database_type.name} database: Always fails!",
            "Waiting 0.01 seconds before next connection attempt",
            f"Trying to connect to {database_type.name} database, attempt #3",
            f"Unsuccessful attempt #3 to connect to {database_type.name} database: Always fails!",
            f"Unable to connect to {database_type.name} database after 3 attempt(s).",
        ]
Exemple #6
0
    def test_retry_database_read_errors_can_be_disabled(
        self, database_type: DatabaseType, caplog: LogCaptureFixture, monkeypatch: MonkeyPatch
    ) -> None:
        caplog.set_level(logging.DEBUG)
        database = Database(database_type)

        mocked_query = Mock(side_effect=[pyodbc.OperationalError("Error 1")])
        monkeypatch.setattr(Session, "query", mocked_query)
        monkeypatch.setattr(master_config, "db_read_retries", 0)

        @retry_database_read_errors
        def query_with_retry() -> bool:
            with database.transaction_context() as session:
                return session.query()  # type: ignore

        with pytest.raises(pyodbc.OperationalError, match="Error 1"):
            assert query_with_retry()

        assert mocked_query.call_count == 1
        assert not (
            "Error 'Error 1' occurred while running query_with_retry. Trying again 1 more time(s) in 1 second(s)."
            in caplog.messages
        )
        assert f"Error during {database} operation, transaction was rolled-back: Error 1" in caplog.messages
Exemple #7
0
 def _run_operation(self, func, *args, **kwargs):
     # execute func in thread pool of attached to cursor connection
     if not self._conn:
         raise pyodbc.OperationalError('Cursor is closed.')
     future = self._conn._execute(func, *args, **kwargs)
     return future
Exemple #8
0
 def fail_twice_then_succeed(connection_string: str, timeout: float) -> pyodbc.Connection:
     nonlocal attempt
     if attempt < 2:
         attempt += 1
         raise pyodbc.OperationalError(f"Test Fail {attempt}")
     return real_connect(connection_string, timeout=timeout)