Switch from MySQL driver to MariaDB
This commit is contained in:
1 parent
3ecda23983
commit
7393b3ecda
11 files changed
+160
-45
No files matched your search
@@ -11,6 +11,15 @@ public abstract class AbstractController {
|
|||||||
*/
|
*/
|
||||||
public abstract String getControllerName();
|
public abstract String getControllerName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance of {@link MysqlDatabase} with the database name as set in the {@link DBController} class
|
||||||
|
*
|
||||||
|
* @return {@link MysqlDatabase}
|
||||||
|
*/
|
||||||
|
protected MysqlDatabase getDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
protected void setDatabase(MysqlDatabase database) {
|
protected void setDatabase(MysqlDatabase database) {
|
||||||
this.database = database;
|
this.database = database;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,22 @@ package netneutrality.db;
|
|||||||
* https://discord.gg/CdFcyQ
|
* https://discord.gg/CdFcyQ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import netneutrality.MusicBot;
|
|
||||||
import netneutrality.ThreadManager;
|
import netneutrality.ThreadManager;
|
||||||
|
import netneutrality.db.entities.EntityInterface;
|
||||||
import netneutrality.db.models.MTableModel;
|
import netneutrality.db.models.MTableModel;
|
||||||
|
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class AsyncMySqlAction {
|
public class AsyncMySqlAction {
|
||||||
|
|
||||||
private String sqlString;
|
private final String sqlString;
|
||||||
private Object[] params;
|
private final Object[] params;
|
||||||
private MysqlDatabase.CommandType type;
|
private final MysqlDatabase.CommandType type;
|
||||||
private MysqlDatabase db;
|
private final MysqlDatabase db;
|
||||||
|
|
||||||
public AsyncMySqlAction(MysqlDatabase db, String sql, Object... params) {
|
public AsyncMySqlAction(MysqlDatabase db, String sql, Object... params) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
@@ -29,28 +32,31 @@ public class AsyncMySqlAction {
|
|||||||
type = MysqlDatabase.CommandType.stringToType(sqlString.toUpperCase().split(" ")[0]);
|
type = MysqlDatabase.CommandType.stringToType(sqlString.toUpperCase().split(" ")[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void async() {
|
||||||
|
async( success -> {} );
|
||||||
|
}
|
||||||
|
|
||||||
public void async(Consumer<MTableModel> success) {
|
public void async(Consumer<MTableModel> success) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INSERT:
|
case INSERT:
|
||||||
ThreadManager.executor.submit(() -> {
|
ThreadManager.dBExecutor.submit(() -> {
|
||||||
db.insert(this.sqlString, this.params);
|
db.insert(this.sqlString, this.params);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
ThreadManager.executor.submit(() -> {
|
ThreadManager.dBExecutor.submit(() -> {
|
||||||
db.update(this.sqlString, this.params);
|
db.update(this.sqlString, this.params);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DELETE:
|
case DELETE:
|
||||||
ThreadManager.executor.submit(() -> {
|
ThreadManager.dBExecutor.submit(() -> {
|
||||||
db.delete(this.sqlString, this.params);
|
db.delete(this.sqlString, this.params);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SELECT:
|
case SELECT:
|
||||||
ThreadManager.executor.submit(() -> {
|
ThreadManager.dBExecutor.submit(() -> {
|
||||||
ResultSet result = db.prepareAndExecute(this.sqlString, this.params);
|
ResultSet result = db.prepareAndExecute(this.sqlString, this.params);
|
||||||
MTableModel table = MysqlDatabase.convertToTableModel(result);
|
MTableModel table = MysqlDatabase.convertToTableModel(result);
|
||||||
|
|
||||||
@@ -60,28 +66,41 @@ public class AsyncMySqlAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void async() {
|
|
||||||
async(o -> {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public MTableModel blocking() {
|
public MTableModel blocking() {
|
||||||
|
try {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INSERT:
|
case INSERT:
|
||||||
|
ThreadManager.dBExecutor.submit(() -> {
|
||||||
db.insert(this.sqlString, this.params);
|
db.insert(this.sqlString, this.params);
|
||||||
|
}).get();
|
||||||
|
|
||||||
case UPDATE:
|
case UPDATE:
|
||||||
|
ThreadManager.dBExecutor.submit(() -> {
|
||||||
db.update(this.sqlString, this.params);
|
db.update(this.sqlString, this.params);
|
||||||
|
}).get();
|
||||||
|
|
||||||
case DELETE:
|
case DELETE:
|
||||||
|
ThreadManager.dBExecutor.submit(() -> {
|
||||||
db.delete(this.sqlString, this.params);
|
db.delete(this.sqlString, this.params);
|
||||||
|
}).get();
|
||||||
|
|
||||||
case SELECT:
|
case SELECT:
|
||||||
|
Callable<MTableModel> task = () -> {
|
||||||
ResultSet result = db.prepareAndExecute(this.sqlString, this.params);
|
ResultSet result = db.prepareAndExecute(this.sqlString, this.params);
|
||||||
|
MTableModel table = MysqlDatabase.convertToTableModel(result);
|
||||||
|
|
||||||
return MysqlDatabase.convertToTableModel(result);
|
return table;
|
||||||
|
};
|
||||||
|
|
||||||
|
Future<MTableModel> future = ThreadManager.dBExecutor.submit(task);
|
||||||
|
return future.get();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import netneutrality.MusicBot;
|
import netneutrality.MusicBot;
|
||||||
import netneutrality.ThreadManager;
|
import netneutrality.ThreadManager;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -25,7 +26,7 @@ public class DBController {
|
|||||||
private final static HashMap<String, AbstractController> controllers = new HashMap<>();
|
private final static HashMap<String, AbstractController> controllers = new HashMap<>();
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(DBController.class);
|
private final static Logger logger = LoggerFactory.getLogger(DBController.class);
|
||||||
private static MysqlDatabase database = new MysqlDatabase("netneutrality");
|
private static final MysqlDatabase database = new MysqlDatabase("netneutrality");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param controller The name of the controller as defined in the {@link AbstractController#getControllerName()}'s method
|
* @param controller The name of the controller as defined in the {@link AbstractController#getControllerName()}'s method
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package netneutrality.db;
|
package netneutrality.db;
|
||||||
|
|
||||||
import com.mysql.cj.jdbc.MysqlConnectionPoolDataSource;
|
|
||||||
|
import org.mariadb.jdbc.MariaDbPoolDataSource;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
|
||||||
public class MysqlConnector {
|
public class MysqlConnector {
|
||||||
|
|
||||||
private String dbName;
|
private final String dbName;
|
||||||
private String dbUser;
|
private final String dbUser;
|
||||||
private String dbHost;
|
private final String dbHost;
|
||||||
private String dbPass;
|
private final String dbPass;
|
||||||
private Connection c;
|
private Connection c;
|
||||||
|
|
||||||
MysqlConnector(String dbName, String dbUser, String dbHost, String dbPass) {
|
MysqlConnector(String dbName, String dbUser, String dbHost, String dbPass) {
|
||||||
@@ -22,20 +22,18 @@ public class MysqlConnector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a MySQL instance using the provided informations
|
* Connect to a MySQL instance using the provided information
|
||||||
*
|
*
|
||||||
* @return {@link MysqlConnector}
|
* @return {@link MysqlConnector}
|
||||||
* @throws SQLException
|
|
||||||
*/
|
*/
|
||||||
public MysqlConnector connect() throws SQLException {
|
public MysqlConnector connect() throws SQLException {
|
||||||
MysqlConnectionPoolDataSource dataSource = new MysqlConnectionPoolDataSource();
|
|
||||||
|
MariaDbPoolDataSource dataSource = new MariaDbPoolDataSource();
|
||||||
dataSource.setUser(dbUser);
|
dataSource.setUser(dbUser);
|
||||||
dataSource.setPassword(dbPass);
|
dataSource.setPassword(dbPass);
|
||||||
dataSource.setServerName(dbHost);
|
dataSource.setServerName(dbHost);
|
||||||
dataSource.setPort(3306);
|
dataSource.setPort(3306);
|
||||||
dataSource.setDatabaseName(dbName);
|
dataSource.setDatabaseName(dbName);
|
||||||
dataSource.setAutoReconnect(true);
|
|
||||||
dataSource.setAutoReconnectForPools(true);
|
|
||||||
c = dataSource.getConnection();
|
c = dataSource.getConnection();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,15 +8,16 @@ import java.sql.SQLException;
|
|||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.sql.Types;
|
import java.sql.Types;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.function.Consumer;
|
import java.util.List;
|
||||||
|
|
||||||
import netneutrality.MusicBot;
|
import netneutrality.MusicBot;
|
||||||
import netneutrality.ThreadManager;
|
import netneutrality.db.entities.EntityInterface;
|
||||||
import netneutrality.db.models.MRowModel;
|
import netneutrality.db.models.MRowModel;
|
||||||
import netneutrality.db.models.MTableModel;
|
import netneutrality.db.models.MTableModel;
|
||||||
import netneutrality.exceptions.UnimplementedParameterException;
|
import netneutrality.exceptions.UnimplementedParameterException;
|
||||||
import netneutrality.handler.LogHandler;
|
import netneutrality.utils.Settings;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ public class MysqlDatabase {
|
|||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(MysqlDatabase.class);
|
private final static Logger logger = LoggerFactory.getLogger(MysqlDatabase.class);
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
private String dbName;
|
private final String dbName;
|
||||||
|
|
||||||
protected enum CommandType {
|
protected enum CommandType {
|
||||||
SELECT("SELECT"), INSERT("INSERT"), UPDATE("UPDATE"), DELETE("DELETE");
|
SELECT("SELECT"), INSERT("INSERT"), UPDATE("UPDATE"), DELETE("DELETE");
|
||||||
@@ -41,16 +42,18 @@ public class MysqlDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected MysqlDatabase(String dbName) {
|
protected MysqlDatabase(String dbName) {
|
||||||
this.dbName = dbName;
|
this.dbName = dbName;
|
||||||
|
String dbUser = Settings.getInstance().get("mysql.user");
|
||||||
|
String dbPass = Settings.getInstance().get("mysql.password");
|
||||||
|
String dbHost = Settings.getInstance().get("mysql.host");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
logger.info("Connecting to database...");
|
logger.info("Connecting to database...");
|
||||||
connection = new MysqlConnector(dbName, "root", "localhost", "").connect().getConnection();
|
connection = new MysqlConnector(dbName, dbUser, dbHost, dbPass).connect().getConnection();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
logger.error("Error connecting to database. Shutting down..");
|
logger.error("Error connecting to database. Shutting down..");
|
||||||
MusicBot.shutdown();
|
MusicBot.shutdown();
|
||||||
System.exit(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +86,7 @@ public class MysqlDatabase {
|
|||||||
* @param params The parameters to include in the query
|
* @param params The parameters to include in the query
|
||||||
* @return an integer of how many row were affected
|
* @return an integer of how many row were affected
|
||||||
*/
|
*/
|
||||||
public int update(String sql, Object... params) {
|
public synchronized int update(String sql, Object... params) {
|
||||||
return executeUpdate(sql, params);
|
return executeUpdate(sql, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +98,7 @@ public class MysqlDatabase {
|
|||||||
* @param params The parameters to include in the query
|
* @param params The parameters to include in the query
|
||||||
* @return an integer of how many row were affected
|
* @return an integer of how many row were affected
|
||||||
*/
|
*/
|
||||||
public int insert(String sql, Object... params) {
|
public synchronized int insert(String sql, Object... params) {
|
||||||
return executeUpdate(sql, params);
|
return executeUpdate(sql, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,11 +110,11 @@ public class MysqlDatabase {
|
|||||||
* @param params The parameters to include in the query
|
* @param params The parameters to include in the query
|
||||||
* @return an integer of how many row were affected
|
* @return an integer of how many row were affected
|
||||||
*/
|
*/
|
||||||
public int delete(String sql, Object... params) {
|
public synchronized int delete(String sql, Object... params) {
|
||||||
return executeUpdate(sql, params);
|
return executeUpdate(sql, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean exists(String table, String key, String value) {
|
public synchronized boolean exists(String table, String key, String value) {
|
||||||
ResultSet rs = prepareAndExecute("SELECT 1 FROM " + table + " WHERE " + key + " = ?", value);
|
ResultSet rs = prepareAndExecute("SELECT 1 FROM " + table + " WHERE " + key + " = ?", value);
|
||||||
try {
|
try {
|
||||||
return rs.next();
|
return rs.next();
|
||||||
@@ -120,8 +123,8 @@ public class MysqlDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int executeUpdate(String sql, Object[] params) {
|
private synchronized int executeUpdate(String sql, Object[] params) {
|
||||||
|
logger.debug("Query: " + sql);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PreparedStatement query = connection.prepareStatement(sql);
|
PreparedStatement query = connection.prepareStatement(sql);
|
||||||
@@ -142,8 +145,7 @@ public class MysqlDatabase {
|
|||||||
* @param params The parameters to include in the query
|
* @param params The parameters to include in the query
|
||||||
* @return a ResultSet object, which can be converted to a model using {@link MysqlDatabase#convertToTableModel(ResultSet)}
|
* @return a ResultSet object, which can be converted to a model using {@link MysqlDatabase#convertToTableModel(ResultSet)}
|
||||||
*/
|
*/
|
||||||
public ResultSet prepareAndExecute(String sql, Object... params) {
|
public synchronized ResultSet prepareAndExecute(String sql, Object... params) {
|
||||||
logger.debug("Query: " + sql);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PreparedStatement query = connection.prepareStatement(sql);
|
PreparedStatement query = connection.prepareStatement(sql);
|
||||||
@@ -151,7 +153,7 @@ public class MysqlDatabase {
|
|||||||
ResultSet rs = query.executeQuery();
|
ResultSet rs = query.executeQuery();
|
||||||
return rs;
|
return rs;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
logger.error(e.toString());
|
logger.error(e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,4 +279,5 @@ public class MysqlDatabase {
|
|||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package netneutrality.exceptions;/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://xtremcommunity.com/
|
||||||
|
* https://discord.gg/CdFcyQ
|
||||||
|
*/
|
||||||
|
|
||||||
|
import netneutrality.handler.LogHandler;
|
||||||
|
|
||||||
|
public class ExecutorException implements Thread.UncaughtExceptionHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
LogHandler.logThread(t, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,4 +22,8 @@ public class LogHandler {
|
|||||||
Settings.getInstance().getLogChannel().sendMessage("Error : " + e).queue();
|
Settings.getInstance().getLogChannel().sendMessage("Error : " + e).queue();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void logThread(Thread t, Throwable e) {
|
||||||
|
logger.error("Exception thrown in thread " + t, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import net.dv8tion.jda.api.entities.Member;
|
|||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
import net.dv8tion.jda.api.entities.PrivateChannel;
|
import net.dv8tion.jda.api.entities.PrivateChannel;
|
||||||
|
import netneutrality.ThreadManager;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ public class MessageRateLimit {
|
|||||||
|
|
||||||
private static Member lastSender;
|
private static Member lastSender;
|
||||||
private static OffsetDateTime timestamp;
|
private static OffsetDateTime timestamp;
|
||||||
private static int cooldown = 500000000; // 1 seconds = 1000000000 nanoseconds
|
private static final long cooldown = 500000000L; // 1 seconds = 1000000000 nanoseconds
|
||||||
|
|
||||||
public synchronized static boolean check(Member member, Message message, MessageChannel channel) {
|
public synchronized static boolean check(Member member, Message message, MessageChannel channel) {
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class NewCommandListener extends ListenerAdapter {
|
|||||||
Message message = event.getMessage();
|
Message message = event.getMessage();
|
||||||
String msg = message.getContentDisplay().trim();
|
String msg = message.getContentDisplay().trim();
|
||||||
|
|
||||||
if (msg.startsWith(Settings.getInstance().getPrefix())) {
|
if (msg.startsWith(Settings.getInstance().get("bot.prefix"))) {
|
||||||
msg = msg.substring(1);
|
msg = msg.substring(1);
|
||||||
String cmd = msg.split(" ", 2)[0];
|
String cmd = msg.split(" ", 2)[0];
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package netneutrality.music;/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://xtremcommunity.com/
|
||||||
|
* https://discord.gg/CdFcyQ
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
|
|
||||||
|
public class LoadResultHandler implements AudioLoadResultHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void trackLoaded(AudioTrack audioTrack) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playlistLoaded(AudioPlaylist audioPlaylist) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noMatches() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFailed(FriendlyException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package netneutrality.thread;/*
|
||||||
|
* Copyright (c) anthorob
|
||||||
|
*
|
||||||
|
* https://xtremcommunity.com/
|
||||||
|
* https://discord.gg/CdFcyQ
|
||||||
|
*/
|
||||||
|
|
||||||
|
import netneutrality.exceptions.ExecutorException;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class BaseThread implements ThreadFactory {
|
||||||
|
|
||||||
|
private final AtomicLong threadId = new AtomicLong(1);
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
public BaseThread(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Thread newThread(@NotNull Runnable r) {
|
||||||
|
Thread thread = new Thread(r);
|
||||||
|
thread.setName(name + "-" + threadId.getAndIncrement());
|
||||||
|
thread.setUncaughtExceptionHandler(new ExecutorException());
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user