mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-04-18 18:30:31 +08:00
Close transaction queue after connection wait on SQLite
Affects issues: - #3436
This commit is contained in:
parent
bf3bdb599d
commit
e041e193fc
@ -148,7 +148,7 @@ public abstract class SQLDB extends AbstractDatabase {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
List<Runnable> unfinishedTransactions = closeTransactionExecutor(transactionExecutor);
|
||||
List<Runnable> unfinishedTransactions = forceCloseTransactionExecutor();
|
||||
this.transactionExecutor = transactionExecutorServiceProvider.get();
|
||||
|
||||
setState(State.PATCHING);
|
||||
@ -167,9 +167,9 @@ public abstract class SQLDB extends AbstractDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
private List<Runnable> closeTransactionExecutor(ExecutorService transactionExecutor) {
|
||||
protected boolean attemptToCloseTransactionExecutor() {
|
||||
if (transactionExecutor == null || transactionExecutor.isShutdown() || transactionExecutor.isTerminated()) {
|
||||
return Collections.emptyList();
|
||||
return true;
|
||||
}
|
||||
transactionExecutor.shutdown();
|
||||
try {
|
||||
@ -179,20 +179,27 @@ public abstract class SQLDB extends AbstractDatabase {
|
||||
logger.warn(TimeSettings.DB_TRANSACTION_FINISH_WAIT_DELAY.getPath() + " was set to over 5 minutes, using 5 min instead.");
|
||||
waitMs = TimeUnit.MINUTES.toMillis(5L);
|
||||
}
|
||||
if (!transactionExecutor.awaitTermination(waitMs, TimeUnit.MILLISECONDS)) {
|
||||
List<Runnable> unfinished = transactionExecutor.shutdownNow();
|
||||
int unfinishedCount = unfinished.size();
|
||||
if (unfinishedCount > 0) {
|
||||
logger.warn(unfinishedCount + " unfinished database transactions were not executed.");
|
||||
}
|
||||
return unfinished;
|
||||
}
|
||||
return transactionExecutor.awaitTermination(waitMs, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected List<Runnable> forceCloseTransactionExecutor() {
|
||||
if (transactionExecutor == null || transactionExecutor.isShutdown() || transactionExecutor.isTerminated()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
List<Runnable> unfinished = transactionExecutor.shutdownNow();
|
||||
int unfinishedCount = unfinished.size();
|
||||
if (unfinishedCount > 0) {
|
||||
logger.warn(unfinishedCount + " unfinished database transactions were not executed.");
|
||||
}
|
||||
return unfinished;
|
||||
} finally {
|
||||
logger.info(locale.getString(PluginLang.DISABLED_WAITING_TRANSACTIONS_COMPLETE));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Patch[] patches() {
|
||||
@ -307,13 +314,18 @@ public abstract class SQLDB extends AbstractDatabase {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// SQLiteDB Overrides this, so any additions to this should also be reflected there.
|
||||
if (getState() == State.OPEN) setState(State.CLOSING);
|
||||
closeTransactionExecutor(transactionExecutor);
|
||||
if (attemptToCloseTransactionExecutor()) {
|
||||
logger.info(locale.getString(PluginLang.DISABLED_WAITING_TRANSACTIONS_COMPLETE));
|
||||
} else {
|
||||
forceCloseTransactionExecutor();
|
||||
}
|
||||
unloadDriverClassloader();
|
||||
setState(State.CLOSED);
|
||||
}
|
||||
|
||||
private void unloadDriverClassloader() {
|
||||
protected void unloadDriverClassloader() {
|
||||
// Unloading class loader using close() causes issues when reloading.
|
||||
// It is better to leak this memory than crash the plugin on reload.
|
||||
|
||||
@ -349,6 +361,8 @@ public abstract class SQLDB extends AbstractDatabase {
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
if (getState() == State.CLOSED) return CompletableFuture.completedFuture(null);
|
||||
|
||||
accessLock.performDatabaseOperation(() -> {
|
||||
if (!ranIntoFatalError.get()) {transaction.executeTransaction(this);}
|
||||
}, transaction);
|
||||
@ -360,6 +374,9 @@ public abstract class SQLDB extends AbstractDatabase {
|
||||
}
|
||||
|
||||
private boolean determineIfShouldDropUnimportantTransactions(int queueSize) {
|
||||
if (getState() == State.CLOSING) {
|
||||
return true;
|
||||
}
|
||||
boolean dropTransactions = dropUnimportantTransactions.get();
|
||||
if (queueSize >= 500 && !dropTransactions) {
|
||||
logger.warn("Database queue size: " + queueSize + ", dropping some unimportant transactions. If this keeps happening disable some extensions or optimize MySQL.");
|
||||
|
@ -201,11 +201,21 @@ public class SQLiteDB extends SQLDB {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
if (getState() == State.OPEN) setState(State.CLOSING);
|
||||
boolean transactionQueueClosed = attemptToCloseTransactionExecutor();
|
||||
if (transactionQueueClosed) logger.info(locale.getString(PluginLang.DISABLED_WAITING_TRANSACTIONS_COMPLETE));
|
||||
|
||||
unloadDriverClassloader();
|
||||
setState(State.CLOSED);
|
||||
|
||||
stopConnectionPingTask();
|
||||
|
||||
logger.info(locale.getString(PluginLang.DISABLED_WAITING_SQLITE));
|
||||
connectionLock.waitUntilNothingAccessing();
|
||||
|
||||
// Transaction queue can't be force-closed before all connections have terminated.
|
||||
if (!transactionQueueClosed) forceCloseTransactionExecutor();
|
||||
|
||||
if (connection != null) {
|
||||
MiscUtils.close(connection);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user