mirror of https://github.com/apache/druid.git
do not explode if mysql transient exception class does not exist (#12213)
Follow up to #12205 to allow druid-mysql-extensions to work with mysql connector/j 8.x again, which does not contain MySQLTransientException, and while would have had the same problem as mariadb if a transient exception was checked, the new check eagerly loads the class when starting up, causing immediate failure.
This commit is contained in:
parent
c4fa3ccfc4
commit
978b8f7dde
|
@ -19,7 +19,6 @@
|
|||
|
||||
package org.apache.druid.metadata.storage.mysql;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
@ -62,10 +61,10 @@ public class MySQLConnector extends SQLMetadataConnector
|
|||
{
|
||||
super(config, dbTables);
|
||||
log.info("Loading \"MySQL\" metadata connector driver %s", driverConfig.getDriverClassName());
|
||||
tryLoadDriverClass(driverConfig.getDriverClassName());
|
||||
tryLoadDriverClass(driverConfig.getDriverClassName(), true);
|
||||
|
||||
if (driverConfig.getDriverClassName().contains("mysql")) {
|
||||
myTransientExceptionClass = tryLoadDriverClass(MYSQL_TRANSIENT_EXCEPTION_CLASS_NAME);
|
||||
myTransientExceptionClass = tryLoadDriverClass(MYSQL_TRANSIENT_EXCEPTION_CLASS_NAME, false);
|
||||
} else {
|
||||
myTransientExceptionClass = null;
|
||||
}
|
||||
|
@ -205,7 +204,11 @@ public class MySQLConnector extends SQLMetadataConnector
|
|||
@Override
|
||||
protected boolean connectorIsTransientException(Throwable e)
|
||||
{
|
||||
return isTransientException(myTransientExceptionClass, e);
|
||||
if (myTransientExceptionClass != null) {
|
||||
return myTransientExceptionClass.isAssignableFrom(e.getClass())
|
||||
|| e instanceof SQLException && ((SQLException) e).getErrorCode() == 1317 /* ER_QUERY_INTERRUPTED */;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -241,28 +244,23 @@ public class MySQLConnector extends SQLMetadataConnector
|
|||
return dbi;
|
||||
}
|
||||
|
||||
private Class<?> tryLoadDriverClass(String className)
|
||||
@Nullable
|
||||
private Class<?> tryLoadDriverClass(String className, boolean failIfNotFound)
|
||||
{
|
||||
try {
|
||||
return Class.forName(className, false, getClass().getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
throw new ISE(e, "Could not find %s on the classpath. The MySQL Connector library is not included in the Druid "
|
||||
+ "distribution but is required to use MySQL. Please download a compatible library (for example "
|
||||
+ "'mysql-connector-java-5.1.48.jar') and place it under 'extensions/mysql-metadata-storage/'. See "
|
||||
+ "https://druid.apache.org/downloads for more details.",
|
||||
className
|
||||
);
|
||||
if (failIfNotFound) {
|
||||
throw new ISE(e, "Could not find %s on the classpath. The MySQL Connector library is not included in the Druid "
|
||||
+ "distribution but is required to use MySQL. Please download a compatible library (for example "
|
||||
+ "'mysql-connector-java-5.1.48.jar') and place it under 'extensions/mysql-metadata-storage/'. See "
|
||||
+ "https://druid.apache.org/downloads for more details.",
|
||||
className
|
||||
);
|
||||
}
|
||||
log.warn("Could not find %s on the classpath.", className);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static boolean isTransientException(@Nullable Class<?> driverClazz, Throwable e)
|
||||
{
|
||||
if (driverClazz != null) {
|
||||
return driverClazz.isAssignableFrom(e.getClass())
|
||||
|| e instanceof SQLException && ((SQLException) e).getErrorCode() == 1317 /* ER_QUERY_INTERRUPTED */;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
|
||||
package org.apache.druid.metadata.storage.mysql;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.mysql.jdbc.exceptions.MySQLTransactionRollbackException;
|
||||
import com.mysql.jdbc.exceptions.MySQLTransientException;
|
||||
import org.apache.druid.metadata.MetadataStorageConnectorConfig;
|
||||
import org.apache.druid.metadata.MetadataStorageTablesConfig;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -29,37 +32,63 @@ import java.sql.SQLTransientConnectionException;
|
|||
|
||||
public class MySQLConnectorTest
|
||||
{
|
||||
@Test
|
||||
public void testIsExceptionTransient()
|
||||
private static final MySQLConnectorDriverConfig MYSQL_DRIVER_CONFIG = new MySQLConnectorDriverConfig();
|
||||
private static final MySQLConnectorDriverConfig MARIADB_DRIVER_CONFIG = new MySQLConnectorDriverConfig()
|
||||
{
|
||||
final Class<?> clazz = MySQLTransientException.class;
|
||||
Assert.assertTrue(MySQLConnector.isTransientException(clazz, new MySQLTransientException()));
|
||||
Assert.assertTrue(MySQLConnector.isTransientException(clazz, new MySQLTransactionRollbackException()));
|
||||
@Override
|
||||
public String getDriverClassName()
|
||||
{
|
||||
return "org.mariadb.jdbc.Driver";
|
||||
}
|
||||
};
|
||||
private static final Supplier<MetadataStorageConnectorConfig> CONNECTOR_CONFIG_SUPPLIER =
|
||||
MetadataStorageConnectorConfig::new;
|
||||
private static final Supplier<MetadataStorageTablesConfig> TABLES_CONFIG_SUPPLIER =
|
||||
() -> new MetadataStorageTablesConfig(null, null, null, null, null, null, null, null, null, null, null);
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsExceptionTransientMySql()
|
||||
{
|
||||
MySQLConnector connector = new MySQLConnector(
|
||||
CONNECTOR_CONFIG_SUPPLIER,
|
||||
TABLES_CONFIG_SUPPLIER,
|
||||
new MySQLConnectorSslConfig(),
|
||||
MYSQL_DRIVER_CONFIG
|
||||
);
|
||||
Assert.assertTrue(connector.connectorIsTransientException(new MySQLTransientException()));
|
||||
Assert.assertTrue(connector.connectorIsTransientException(new MySQLTransactionRollbackException()));
|
||||
Assert.assertTrue(
|
||||
MySQLConnector.isTransientException(clazz, new SQLException("some transient failure", "wtf", 1317))
|
||||
connector.connectorIsTransientException(new SQLException("some transient failure", "wtf", 1317))
|
||||
);
|
||||
Assert.assertFalse(
|
||||
MySQLConnector.isTransientException(clazz, new SQLException("totally realistic test data", "wtf", 1337))
|
||||
connector.connectorIsTransientException(new SQLException("totally realistic test data", "wtf", 1337))
|
||||
);
|
||||
// this method does not specially handle normal transient exceptions either, since it is not vendor specific
|
||||
Assert.assertFalse(
|
||||
MySQLConnector.isTransientException(clazz, new SQLTransientConnectionException("transient"))
|
||||
connector.connectorIsTransientException(new SQLTransientConnectionException("transient"))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsExceptionTransientNoMySqlClazz()
|
||||
{
|
||||
MySQLConnector connector = new MySQLConnector(
|
||||
CONNECTOR_CONFIG_SUPPLIER,
|
||||
TABLES_CONFIG_SUPPLIER,
|
||||
new MySQLConnectorSslConfig(),
|
||||
MARIADB_DRIVER_CONFIG
|
||||
);
|
||||
// no vendor specific for MariaDb, so should always be false
|
||||
Assert.assertFalse(MySQLConnector.isTransientException(null, new MySQLTransientException()));
|
||||
Assert.assertFalse(connector.connectorIsTransientException(new MySQLTransientException()));
|
||||
Assert.assertFalse(
|
||||
MySQLConnector.isTransientException(null, new SQLException("some transient failure", "wtf", 1317))
|
||||
connector.connectorIsTransientException(new SQLException("some transient failure", "wtf", 1317))
|
||||
);
|
||||
Assert.assertFalse(
|
||||
MySQLConnector.isTransientException(null, new SQLException("totally realistic test data", "wtf", 1337))
|
||||
connector.connectorIsTransientException(new SQLException("totally realistic test data", "wtf", 1337))
|
||||
);
|
||||
Assert.assertFalse(
|
||||
MySQLConnector.isTransientException(null, new SQLTransientConnectionException("transient"))
|
||||
connector.connectorIsTransientException(new SQLTransientConnectionException("transient"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue